观察者模式(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 也可以实现一对多的观察者通知。