观察者模式
什么是观察者模式?
观察者模式定义了对象之间的一种一对多依赖关系,允许多个观察者对象同时监听某一个主题对象。这种模式是事件驱动编程的核心,其主要目标是实现对象间的松耦合。松耦合的设计允许我们构建灵活的系统,组件可以独立于其他组件进行扩展和修改。
观察者模式的关键参与者
观察者模式的实现涉及两类对象:
-
主题(Subject): 拥有重要状态的对象,当这个状态发生变化时,需要通知所有注册的观察者。主题提供接口,允许观察者对象订阅或取消订阅事件通知。
-
观察者(Observer): 感兴趣于主题状态变化的对象。每个观察者都必须实现一个更新接口,以便在状态变化时被通知。
观察者模式的工作原理
当主题的状态发生变化时,它会自动通知所有订阅者(即观察者)。观察者获得状态更新的通知后,可以执行相应的动作。这种通信机制对于实现如图形用户界面(GUI)系统、游戏开发或者实时数据处理等领域至关重要。
观察者模式的优点
-
松耦合设计:观察者与主题之间的交互减少了相互依赖,使得单独修改观察者或主题变得简单而不影响其他部分。
-
动态订阅:对象可以在运行时动态地订阅或取消订阅事件,增强了灵活性。
-
广播通信:主题可以向所有感兴趣的观察者广播通知,这是一种有效的通信方式。
//观察者模式 (发布——订阅)设计模式 //行为性模式:主要关注的是对象之间的通信 //主要关注的是对象的一对多的关系,也就是多个对象都依赖一个对象,当该对象的状态发生改变时 //其它对象都能够接收到相应的通知 /* Observer1 Observer2 Observer3 Subject(主题) 主题有更改,应该及时通知相应的观察者 处理相应的事件 */ class Observer { public: virtual void handle(int msgid) = 0;//处理消息的接口 }; //第一个实例 class Observer1 : public Observer { public: void handle(int msgid){ switch(msgid) { case 2: cout<<"Observer2 recv 2 msg"<<endl; break; default: cout<<"Observer2 recv unknow msg"<<endl; break; } } }; //第二个实例 class Observer2 : public Observer { public: void handle(int msgid){ switch(msgid) { case 1: cout<<"Observer3 recv 1 msg"<<endl; break; case 2: cout<<"Observer3 recv 3 msg"<<endl; break; default: cout<<"Observer3 recv unknow msg"<<endl; break; } } }; //第三个实例 class Observer3 : public Observer { public: void handle(int msgid){ switch(msgid) { case 1: cout<<"Observer recv 1 msg"<<endl; break; case 2: cout<<"Observer recv 2 msg"<<endl; break; default: cout<<"Observer recv unknow msg"<<endl; break; } } }; class Subject { public: //给主题增加观察者对象 void addObserver(Observer* obser, int msgid) { _subMap[msgid].push_back(obser); //如果键存在就返回它所对应的引用,如果不存在他会插入 } //主题检测发生改变,通知相应的观察者对象处理事件 void dispath(int msgid)//有相应的事情发生了 我就通知它 { auto it = _subMap.find(msgid); if(it != _subMap.end()) { for(Observer *pobser : it->second) { pObser->handle(msgid); } } } private: //多个消息对一个时间感兴趣 所以要弄一个队列 unordered_map<int,list<Observer*>> _subMap; }; int main() { Subject subject; Observer *p1 = new Observer1(); Observer *p2 = new Observer2(); Observer *p3 = new Observer3(); subject.addObserver(p1,1); subject.addObserver(p1,2); subject.addObserver(p2,2); subject.addObserver(p3,1); subject.addObserver(p3,3); int msgid = 0; for(;;) { cout<<"输入消息id"; cin>>msgid; if(msgid == -1 ) break; } return 0; }