设计模式-行为-Observer(观察者)模式
典型的应用就是MVC模式
定义了一对多的关系,一个对象的改变,所依赖的其他对象都将获得通知并且更新。
场景1:看电视,喜欢看这个频道的 会选择看这个频道,
场景2:类似于订阅自己关心的状态,该状态的消息来了,那么就会得到通知
观察者模式缺点也很明显
1.每次都要广播筛选 合适的观察者
例1
头文件 #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
游戏中实现的观察者实例
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
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 就能实现一对多了