【观察者模式】

观察者模式

什么是观察者模式?

观察者模式定义了对象之间的一种一对多依赖关系,允许多个观察者对象同时监听某一个主题对象。这种模式是事件驱动编程的核心,其主要目标是实现对象间的松耦合。松耦合的设计允许我们构建灵活的系统,组件可以独立于其他组件进行扩展和修改。

观察者模式的关键参与者

观察者模式的实现涉及两类对象:

  • 主题(Subject): 拥有重要状态的对象,当这个状态发生变化时,需要通知所有注册的观察者。主题提供接口,允许观察者对象订阅或取消订阅事件通知。

  • 观察者(Observer): 感兴趣于主题状态变化的对象。每个观察者都必须实现一个更新接口,以便在状态变化时被通知。

观察者模式的工作原理

当主题的状态发生变化时,它会自动通知所有订阅者(即观察者)。观察者获得状态更新的通知后,可以执行相应的动作。这种通信机制对于实现如图形用户界面(GUI)系统、游戏开发或者实时数据处理等领域至关重要。

观察者模式的优点

  1. 松耦合设计:观察者与主题之间的交互减少了相互依赖,使得单独修改观察者或主题变得简单而不影响其他部分。

  2. 动态订阅:对象可以在运行时动态地订阅或取消订阅事件,增强了灵活性。

  3. 广播通信:主题可以向所有感兴趣的观察者广播通知,这是一种有效的通信方式。

复制代码
 //观察者模式  (发布——订阅)设计模式
 //行为性模式:主要关注的是对象之间的通信
 //主要关注的是对象的一对多的关系,也就是多个对象都依赖一个对象,当该对象的状态发生改变时
 //其它对象都能够接收到相应的通知 
 /*
 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;
 }
相关推荐
hansang_IR15 小时前
【题解】LC:倍增 / 区间并查集(Range Parallel Unionfind)
c++·算法·并查集
东东最爱敲键盘15 小时前
day7.c++继承
c++
沫璃染墨16 小时前
《从零入门Linux系统篇(十五):系统工具篇·六——GDB调试器详解:从程序执行控制到高级调试技巧》
linux·运维·服务器·c语言·c++
吃着火锅x唱着歌16 小时前
Effective C++ 学习笔记 条款40 明智而审慎地使用多重继承
c++·笔记·学习
醉城夜风~16 小时前
(超详细)C++ STL list容器详解:从使用方法到双向链表底层原理全面解析
c++·windows
烟花落o17 小时前
C++ 从 C 到进阶 ②:引用、inline 、nullptr
c++·引用·inline·nullptr·c++入门
liulilittle17 小时前
MOE路由:路由(logits: top-k/8)
c++·人工智能·算法·机器学习·llm
旖旎夜光17 小时前
LeetCode 11:盛最多水的容器(双指针问题) —— 题解
数据结构·c++·算法·leetcode·双指针
我不会插花弄玉19 小时前
15.map,set下:AVL树,红黑树和map,set的封装【由浅入深-C++】
c++·stl
hold?fish:palm20 小时前
20 旋转图像
c++·算法·leetcode