• 【C++基础】观察者模式(“发布-订阅”模式)


      本文参考:观察者模式 - 摩根斯 | 爱编程的大丙

    观察者模式允许我们定义一种订阅机制,可在对象事件发生时通知所有的观察者对象,使它们能够自动更新。观察者模式还有另外一个名字叫做“发布-订阅”模式。

    发布者:

    添加订阅者,将所有的订阅者存储起来
    删除订阅者,将其从订阅者列表中删除
    将消息发送给订阅者(发通知)

    下面举一个生动的例子:

    NewsAgency是一个抽象类,表示发布者,其派生类为 Morgans和Gossip,代表不同的两个报社

    NewAgency.h

    1. #pragma once
    2. #include
    3. #include
    4. using namespace std;
    5. //声明订阅者类
    6. class Observer;
    7. class NewsAgency
    8. {
    9. public:
    10. void attach(Observer* ob); //添加订阅者
    11. void deatch(Observer* ob); //删除订阅者
    12. virtual void notify(string msg) = 0; //通知list中的所有订阅者
    13. virtual ~NewsAgency() {}; //析构
    14. protected:
    15. list m_list; //存储订阅者对象
    16. };
    17. class Morgans :public NewsAgency
    18. {
    19. public:
    20. void notify(string msg) override;
    21. };
    22. class Gossip :public NewsAgency
    23. {
    24. public:
    25. void notify(string msg) override;
    26. };

     在NewsAgency.cpp,重写子类的虚函数。

    1. #include "NewsAgency.h"
    2. #include "Observer.h"
    3. #include
    4. void NewsAgency::attach(Observer* ob)
    5. {
    6. m_list.push_back(ob);
    7. }
    8. void NewsAgency::deatch(Observer* ob)
    9. {
    10. m_list.remove(ob);
    11. }
    12. void Morgans::notify(string msg)
    13. {
    14. cout << "摩根斯新闻社报纸的订阅者一共有" << m_list.size() << endl;
    15. for (const auto& item : m_list)
    16. {
    17. item->update(msg); // 订阅者类的定义在下面
    18. }
    19. }
    20. void Gossip::notify(string msg)
    21. {
    22. cout << "八卦新闻社报纸的订阅者一共有 " << m_list.size() << endl;
    23. for (const auto& item : m_list)
    24. {
    25. item->update(msg);
    26. }
    27. }

    订阅者(也可称为观察者):

     Observer.h

    首先给所有的观察者定义一个抽象的基类。

    然后子类在各自的类中分别重写了update()这个状态更新函数

    1. #pragma once
    2. #include
    3. #include
    4. #include "NewsAgency.h"
    5. //抽象的订阅者类
    6. class Observer
    7. {
    8. public:
    9. //需要通过构造函数给观察者类提供一个信息的发布者
    10. //通过发布者对象将观察者对象存储了起来,这样就可以收到发布者推送的消息了。
    11. Observer(string name, NewsAgency* news)
    12. :m_name(name), m_news(news)
    13. {
    14. m_news->attach(this);
    15. }
    16. //观察者取消订阅,取消之后将不再接收订阅消息。
    17. void unsubscribe()
    18. {
    19. m_news->deatch(this);
    20. }
    21. //观察者得到最新消息之后,用于更新自己当前的状态。
    22. virtual void update(string msg) = 0;
    23. virtual ~Observer() {};
    24. protected:
    25. string m_name;
    26. NewsAgency* m_news;
    27. };
    28. class Dragon :public Observer
    29. {
    30. public:
    31. using Observer::Observer;
    32. void update(string msg) override
    33. {
    34. cout<< "路飞的老爸革命军龙收到消息: " << msg << endl;
    35. }
    36. };
    37. class Shanks : public Observer
    38. {
    39. public:
    40. using Observer::Observer;
    41. void update(string msg) override
    42. {
    43. cout << "路飞的引路人红发香克斯收到消息: " << msg << endl;
    44. }
    45. };
    46. class Bartolomeo : public Observer
    47. {
    48. public:
    49. using Observer::Observer;
    50. void update(string msg) override
    51. {
    52. cout << "路飞的头号粉丝巴托洛米奥收到消息: " << msg << endl;
    53. }
    54. };

    main函数:

    1. #include
    2. #include "NewsAgency.h"
    3. #include "Observer.h"
    4. using namespace std;
    5. int main()
    6. {
    7. Morgans* ms = new Morgans;
    8. Gossip* gossip = new Gossip;
    9. Dragon* dragon = new Dragon("蒙奇·D·龙", ms);
    10. Shanks* shanks = new Shanks("香克斯", ms);
    11. Bartolomeo* barto = new Bartolomeo("巴托洛米奥", gossip);
    12. ms->notify("蒙奇·D·路飞成为新世界的新的四皇之一, 赏金30亿贝里!!!");
    13. cout << "======================================" << endl;
    14. gossip->notify("女帝汉库克想要嫁给路飞, 给路飞生猴子, 哈哈哈...");
    15. delete ms;
    16. delete gossip;
    17. delete dragon;
    18. delete shanks;
    19. delete barto;
    20. }

    最后总结一下观察者模式的应用场景:
    当一个对象的状态发生变化,并且需要改变其它对象的时候;或者当应用中一些对象必须观察其它对象的时候可以使用观察者模式。

  • 相关阅读:
    NLP时政有害信息的界定
    Selenium UI 自动化
    如何快速搭建自己的查题公众号教程
    Kubeadm 安装 k8s kubelet status failed
    哪款电容笔适用于ipad2017?Ipad2017推荐电容笔
    计算机网络期末98+冲刺笔记
    78-基于STM32单片机的DDS函数信号波形发生器(实物图+源码+原理图+PCB+论文)全套资料
    超详细BootLoader原理分析
    python和Springboot如何交互?
    linux 学习 day 07 进程信号
  • 原文地址:https://blog.csdn.net/weixin_42809675/article/details/132819235