• 观察者模式 行为型设计模式之七


    1.定义

            在GOF的《设计模式:可复用面向对象软件的基础》一书中对观察者模式是这样定义的:定义对象的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。当一个对象发生了变化,关注它的对象就会得到通知;这种交互也成为发布-订阅(publish-subscribe)。

    2.组成结构

    1. Subject(目标):目标知道它的观察者,可以有任意多个观察者观察用一个目标,提供注册和删除观察者对象的接口。
    2. Observer(观察者):为所有观察目标的观察者对象提供一个公共的更新接口。
    3. ConcreteSubject(具体目标):将有关状态的情况广播给各ConcreteObserver对象。
    4. ConcreteObserver(具体观察者):维护一个指向ConcreteSubject对象的指针,用于当具体观察者初始化时直接存入ConcreteSubject对象(初始化就订阅ConcreteSubject主题);存储有有关状态,这些状态应与目标的状态保持一致;实现Observer公共更新接口以便使自身状态和目标状态保持一致。

    3.示例代码

    1. #include
    2. #include
    3. using std::cout;
    4. using std::endl;
    5. using std::cin;
    6. class Observer
    7. {
    8. public:
    9. virtual ~Observer() {};
    10. virtual void Update(int) = 0;
    11. };
    12. class Subject
    13. {
    14. public:
    15. virtual ~Subject() {};
    16. virtual void Attach(Observer*) = 0;
    17. virtual void Detach(Observer*) = 0;
    18. virtual void Notify() = 0;
    19. };
    20. class ConcreteObserver : public Observer
    21. {
    22. private:
    23. Subject* _pSubject;
    24. public:
    25. ConcreteObserver(Subject* pSubject) :_pSubject(pSubject)
    26. {
    27. //在目标中注册当前观察者(此处的观察者是广义上的观察者,目标并不知道具体谁要观察它,目标只进行广播即可)
    28. this->_pSubject->Attach(this);
    29. cout << "I'm the observer \" 1 \".\n";
    30. }
    31. void Update(int value) override
    32. {
    33. cout << "ConcreteObserver get the update.New State:" << value << endl;
    34. }
    35. };
    36. class ConcreteObserver2 : public Observer
    37. {
    38. private:
    39. Subject* _pSubject;
    40. public:
    41. ConcreteObserver2(Subject* pSubject) :_pSubject(pSubject)
    42. {
    43. //在目标中注册当前观察者(此处的观察者是广义上的观察者,目标并不知道具体谁要观察它,目标只进行广播即可)
    44. this->_pSubject->Attach(this);
    45. cout << "I'm the observer \" 2 \".\n";
    46. }
    47. void Update(int value) override
    48. {
    49. cout << "ConcreteObserver2 get the update.New State:" << value << endl;
    50. }
    51. };
    52. class ConcreteSubject :public Subject
    53. {
    54. private:
    55. std::list _pObserverList;
    56. int _iState;
    57. public:
    58. void SetState(int state)
    59. {
    60. _iState = state;
    61. }
    62. void Attach(Observer* pObserver) override
    63. {
    64. _pObserverList.push_back(pObserver);
    65. }
    66. void Detach(Observer* pObserver) override
    67. {
    68. _pObserverList.remove(pObserver);
    69. }
    70. void Notify() override
    71. {
    72. auto begin = _pObserverList.begin();
    73. auto end = _pObserverList.end();
    74. while (begin != end)
    75. {
    76. (*begin)->Update(_iState);
    77. begin++;
    78. }
    79. }
    80. };
    81. int main()
    82. {
    83. //创建目标
    84. ConcreteSubject* pSubject = new ConcreteSubject();
    85. //创建观察者
    86. Observer* pObserver = new ConcreteObserver(pSubject);
    87. Observer* pObserver2 = new ConcreteObserver2(pSubject);
    88. //改变当前状态
    89. pSubject->SetState(2);
    90. //广播给所有广义上的观察者
    91. pSubject->Notify();
    92. //去除某个观察者
    93. pSubject->Detach(pObserver);
    94. //改变当前状态
    95. pSubject->SetState(3);
    96. //重新广播
    97. pSubject->Notify();
    98. //结束,释放对象
    99. delete pObserver;
    100. delete pObserver2;
    101. delete pSubject;
    102. return 0;
    103. }

    4.使用说明

    意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。

    主要解决:一个对象状态改变并给其它对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

    何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

    如何解决:使用面向对象技术,可以将这种依赖关系弱化。

    关键代码:在抽象类里有一个arrayList存放观察者们。

    应用实例:1、拍卖的时候,拍卖师观察最高价格,然后通知给其它竞价者竞价。2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水找来一个老乌龟,这个老乌龟就是观察者(菩萨是被观察者),他观察菩萨这个动作。

    优点:1、观察者和被观察者是抽象耦合的。2、建立一套触发机制。

    缺点:1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

    使用场景:

    1. 一个抽象模型有两个方面,其中一个方面发依赖于另外一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
    2. 一个对象的改变将导致其它一个或多个对象发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
    3. 一个对象必须通知其他对象,而并不知道这些对象是谁。
    4. 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

    注意事项:1、应避免循环引用。2、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式(多线程)。
     

    引用

    C++观察者模式_c++ observer-CSDN博客

     

  • 相关阅读:
    MQ---第一篇
    带权有向图最短路径之Dijkstra和Floyd
    shopee买家通系统一款全自动化操作的软件
    Spring注解开发
    数据结构学习笔记(三)——树与二叉树
    JavaScript中获取数组中的元素数量及去重
    微信小程序是什么?如何快速搭建一个微信小程序?
    echarts文档解读
    c++学习之十四
    Qt-OpenCV学习笔记--基础知识和基本操作--总结
  • 原文地址:https://blog.csdn.net/Physics_ITBoy/article/details/133637239