观察者模式(Observer Pattern)是典型的行为型设计模式,MVC 架构就是其经典应用。它定义了一对多的依赖关系:当一个对象的状态发生改变时,所有依赖它的对象都会收到通知并自动更新。

适用场景

  • 场景1:观看电视频道——观众主动订阅感兴趣的频道,频道有内容时通知订阅者。
  • 场景2:消息订阅——订阅自己关心的状态,当该状态的消息到达时自动得到通知。

缺点

  • 每次状态变更都需要广播,并逐一筛选合适的观察者,在观察者数量较多时开销较大。

例1:C++ 基础实现

头文件
                #include "PublicHeaders.h"
                
                
                #include <vector>
                #include <string>
                
                class Observer;
                
                class Subject
                {
                public:
                	virtual void Attach(Observer*) = 0;
                	virtual void Detach(Observer*) = 0;
                	virtual void Notify() = 0;
                
                	void setState(const std::string&state)
                	{
                		this->_state = state;
                	}
                	const std::string& getState()const
                	{
                		return _state;
                	}
                private:
                	std::string _state;
                protected:
                
                	std::vector<Observer*> _observers;
                
                };
                
                
                class ConCreateSubject :public Subject
                {
                public:
                	virtual void Attach(Observer*) override;
                	virtual void Detach(Observer*)override;
                	virtual void Notify() override;
                
                
                };
                
                class  Observer
                {
                public:
                	virtual void Update(const std::string &state) = 0;
                };
                
                class ConCreateObserverA :public Observer
                {
                public:
                	virtual void Update(const std::string& state)override
                	{
                		if (state == "A")
                		{
                			cout << __FUNCTION__ << endl;
                		}
                	}
                };
                
                
                class ConCreateObserverB :public Observer
                {
                public:
                	virtual void Update(const std::string& state)override
                	{
                		if (state == "B")
                		{
                			cout << __FUNCTION__ << endl;
                		}
                	}
                };
                
                
                void testObserver();
                
                
                
                源文件
                #include "Observer.h"
                
                void ConCreateSubject::Attach(Observer*observer)
                {
                	_observers.push_back(observer);
                }
                
                void ConCreateSubject::Detach(Observer*observer)
                {
                	auto iter = std::find(_observers.begin(), _observers.end(), observer);
                	if (iter != _observers.end())
                	{
                		_observers.erase(iter);
                	}
                
                }
                
                void ConCreateSubject::Notify()
                {
                	for (int i = 0; i < _observers.size(); ++i)
                	{
                		_observers[i]->Update(this->getState());
                	}
                }
                
                
                
                
                void testObserver()
                {
                	ConCreateSubject *sub = new ConCreateSubject;
                
                	auto a1 = new ConCreateObserverA;
                	sub->Attach(a1);
                
                	auto a2 = new ConCreateObserverA;
                	sub->Attach(a2);
                
                	auto b1 = new ConCreateObserverB;
                	sub->Attach(b1);
                
                	sub->setState("A");
                
                	sub->Notify();
                
                	sub->Detach(a1);
                
                
                	sub->Notify();
                
                }

例2:Unity C# 游戏中的观察者实例

以下是在游戏中实现的观察者中心(NotifyCenter)示例。

using UnityEngine;
                using System.Collections;
                using System.Collections.Generic;
                
                
                public delegate void HandlerNotifyCenter(System.Object arg);
                
                
                
                [System.Serializable]
                class Recver
                {
                
                    public string name;
                    public GameObject recver;
                
                    public HandlerNotifyCenter handler;
                    public Recver()
                    {
                
                
                    }
                
                    public void InVoke(System.Object arg)
                    {
                        handler(arg);
                    }
                }
                
                
                public class NotifyCenter : MonoBehaviour
                {
                    static public NotifyCenter ins;
                
                    List<Recver> recvers = new List<Recver>();
                
                
                
                    void Awake()
                    {
                        ins = this;
                    }
                    // Use this for initialization
                    void Start()
                    {
                
                    }
                
                    // Update is called once per frame
                    void Update()
                    {
                
                    }
                
                
                
                    public void addRecver(GameObject recver, string name, HandlerNotifyCenter handler)
                    {
                        // gameObject.SendMessage(msg);
                
                        Recver x = new Recver();
                        x.name = name;
                        x.handler = handler;
                        x.recver = recver;
                        recvers.Add(x);
                    }
                
                
                    public void removeRecver(GameObject recver, string name)
                    {
                        foreach (Recver obj in recvers)
                        {
                            if (name == obj.name && recver == obj.recver)
                            {
                                recvers.Remove(obj);
                            }
                        }
                
                
                
                    }
                
                    public void sendMessage(string msg, System.Object arg)
                    {
                        foreach (Recver obj in recvers)
                        {
                            if (msg == obj.name)
                            {
                                obj.InVoke(arg);
                            }
                        }
                    }
                
                }
                
                
                
                添加观察者
                    NotifyCenter x = NotifyCenter.ins;
                    x.addRecver(gameObject, "addCoin", new HandlerNotifyCenter(addCoin));
                    public void addCoin(System.Object obj)
                    {
                
                
                    }

例3:C++ 基于 unordered_map 的简化实现

class NotifyCenter
                {
                public:
                	static NotifyCenter *ins;
                	static NotifyCenter*getInstance()
                	{
                		if (ins == nullptr)
                		{
                			ins = new NotifyCenter;
                		}
                		return ins;
                	}
                
                	void SendMessage(string name, void* data)
                	{
                		auto &func = _listeners[name];
                		if (func )
                		{
                			func(data);
                		}
                	}
                
                	void addListener(string name, std::function<void(void*data)>  callback)
                	{
                		_listeners[name] = callback;
                	}
                
                
                private:
                	std::unordered_map<  string, std::function<void(void*data)>  >  _listeners;
                
                };
                
                NotifyCenter*NotifyCenter::ins = nullptr;
                
                
                
                int main()
                {
                
                	//添加接受者
                	NotifyCenter::getInstance()->addListener("john", [=](void *data)
                	{//回调
                
                		cout << (char*)data<<"   call me " << endl;
                	});
                
                	//添加接受者
                
                	NotifyCenter::getInstance()->addListener("jack", [=](void *data)
                	{
                		//回调
                
                		cout << (char*)data << "   call me " << endl;
                	});
                
                
                	//发送消息
                	NotifyCenter::getInstance()->SendMessage("john","hk");
                
                	//发送消息
                	NotifyCenter::getInstance()->SendMessage("john", "");
                
                	//发送消息
                	NotifyCenter::getInstance()->SendMessage("11", "");
                
                
                	system("pause");
                
                	return 0;
                }

当然用 vector 也可以实现一对多的观察者通知。