意图:

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

动机:

将一个系统设计成一系列相互协作的类有一个常见的副作用:需要维护相关对象之间的一致性。

观察者模式定义一种交互,即发布-订阅:

  • 一个对象当自身状态发生改变时,会发出通知,但是并不知道谁是他的接收者,但每个接收者都会接收到通知,这些接受者称为观察者。
  • 作为对通知的响应,每个观察者都将查询目标状态,然后改变自身的状态以和目标状态进行同步。

使用场景:

  • 使对象封装为独立的改变和使用;
  • 一个对象改变同时需要改变其它对象,而不知道具体有多少对象需要改变;
  • 不希望对象是紧耦合的。

结构:

参与者:

Subject:目标,知道它的观察者,提供注册和删除观察者对象的接口

Observer:观察者,为那些在目标发生改变时需获得通知的对象定义一个更新接口

ConcreteSubject:具体目标,存储对象状态,状态改变时,向各个观察者发出通知

ConcreteObserver:具体观察者,维护一个指向ConcreteSubject对象的引用,存储有关状态,实现更新接口update,使自身状态与目标的状态保持一致

优缺点:

1 目标和观察者之间松耦合

2 支持广播通信:Subject发送的通知不需要指定它的接受者。通知被自动广播给所有已向该目标对象登记的有关对象。

3 意外的更新:看似无害的操作可能会引起观察者错误的更新。


示例代码:

  1. /*
  2. * 观察者模式
  3. * 情景:高数课,ABCD四位同学,A是好学生,去上课,B在寝室睡觉,C在网吧打游戏,D在学校外陪女友逛街
  4. * 他们约定,如果要点名了,A在QQ群里吼一声,他们立刻赶到教室去。
  5. * 采用观察者模式实现这个情景的应用。
  6. */
  7.  
  8. #include <iostream>
  9. #include <string>
  10. #include <list>
  11.  
  12. class Observer;
  13.  
  14. class Subject{
  15. public:
  16. virtual ~Subject() {};
  17. virtual void registerObsvr(Observer* obsvr) = ;
  18. virtual void removeObsvr(Observer* obsvr) = ;
  19. virtual void notifyObsvrs(const std::string &msg) = ;
  20. };
  21. class Observer {
  22. public:
  23. virtual ~Observer() {};
  24. virtual void Update(const std::string &msg)= ;
  25. virtual std::string getName() = ;
  26. protected:
  27. Observer(){};
  28. };
  29.  
  30. // -------------------------------------------------
  31. class QQGroup : public Subject {
  32. public:
  33. QQGroup() { _observers = new std::list<Observer*>(); }
  34. void registerObsvr(Observer* obsvr);
  35. void removeObsvr(Observer* obsvr);
  36. void notifyObsvrs(const std::string &msg);
  37. private:
  38. std::list<Observer*> *_observers;
  39. };
  40.  
  41. void QQGroup::registerObsvr(Observer* obsvr) {
  42. _observers->push_back(obsvr);
  43. }
  44.  
  45. void QQGroup::removeObsvr(Observer* obsvr) {
  46. if (_observers->size() > )
  47. _observers->remove(obsvr);
  48. }
  49. void QQGroup::notifyObsvrs( const std::string &msg) {
  50. std::cout << "群消息:" << msg << std::endl;
  51. std::list<Observer*>::iterator iter
  52. = _observers->begin();
  53. for ( ;iter != _observers->end(); iter++ ) {
  54. (*iter)->Update(msg);
  55. }
  56. }
  57.  
  58. // ------------------------------------------------
  59. class RoomMate : public Observer {
  60. public:
  61. RoomMate(std::string name, std::string now ,std::string action)
  62. {
  63. _name = name;
  64. _action = action;
  65. _now = now;
  66. };
  67. void Update( const std::string &msg);
  68. std::string getName();
  69. private:
  70. std::string _name;
  71. std::string _action;
  72. std::string _now;
  73. };
  74.  
  75. std::string RoomMate::getName() {
  76. return _name;
  77. }
  78.  
  79. void RoomMate::Update(const std::string &msg) {
  80. std::cout<< "This is " << _name << std::endl;
  81. if ( msg == "点名了" )
  82. std::cout << "Action: " << _action
  83. << std::endl << std::endl;
  84. else
  85. std::cout << "Go on:" << _now
  86. << std::endl << std::endl ;
  87. }
  88.  
  89. //测试代码
  90. int main()
  91. {
  92. RoomMate* B = new RoomMate("B",
  93. "sleeping",
  94. "get dressed and run to classroom");
  95. RoomMate* C = new RoomMate("C",
  96. "playing games",
  97. "pay the fee and run to classroom");
  98. RoomMate* D = new RoomMate("D",
  99. "shopping with girl friend",
  100. "go back to school and be worried about girl friend's angry");
  101.  
  102. QQGroup* qqgroup = new QQGroup();
  103. qqgroup->registerObsvr(B);
  104. qqgroup->registerObsvr(C);
  105. qqgroup->registerObsvr(D);
  106.  
  107. qqgroup->notifyObsvrs("目前没点名");
  108. qqgroup->notifyObsvrs("点名了");
  109.  
  110. system("Pause");
  111. return ;
  112. }

运行截图

相关模式:

中介者模式:通过封装负责的更新条件来实现对象间的交互

观察者模式:使用广播-接收模式实现对象间的交互,不需要维护一个复杂的中介者类

参考资料:

《设计模式:可复用面向对象软件的基础》

设计模式----观察者模式(C++)

设计模式(16) 观察者模式(OBSERVER)C++实现的更多相关文章

  1. 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)

    原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...

  2. 8.5 GOF设计模式四: 观察者模式Observer

    GOF设计模式四: 观察者模式Observer  现实中遇到的问题  当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式  观察者模式 ...

  3. 人人都会设计模式:观察者模式--Observer

    https://segmentfault.com/a/1190000012295887 观察者模式是抽像通知者和观察者,达到具体通知者跟具体观察者没有偶合.能达到不管是切换通知者,或者是切换观察者,都 ...

  4. 二十四种设计模式:观察者模式(Observer Pattern)

    观察者模式(Observer Pattern) 介绍定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新. 示例有一个Message实体类,某些对象 ...

  5. [设计模式] 19 观察者模式 Observer Pattern

    在GOF的<设计模式:可复用面向对象软件的基础>一书中对观察者模式是这样说的:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.当一个 ...

  6. c#设计模式之观察者模式(Observer Pattern)

    场景出发 一个月高风黑的晚上,突然传来了尖锐的猫叫,宁静被彻底打破,狗开始吠了,大人醒了,婴儿哭了,小偷跑了 这个过程,如果用面向对象语言来描述,简单莫过于下: public class Cat { ...

  7. JAVA设计模式之观察者模式 - Observer

    有趣的事情发生时,可千万别错过了!有一个模式可以帮你的对象知悉现况,不会错过该对象感兴趣的事.对象甚至在运行时可决定是否要继续被通知.有了观察者,你将会消息灵通. 介绍 观察者模式的定义: 在对象之间 ...

  8. 设计模式之观察者模式(Observer pattern)

    最近参加了一次面试,其中笔试题有一道编程题,在更换掉试题的描述场景后,大意如下: 上课铃声响起,学生A/B/C/D进入教室:下课铃声响起,学生A/B/C/D离开教室. 要求使用设计模式的思想完成铃与学 ...

  9. 设计模式之观察者模式(Observer)

    观察者模式原理:当有新的消息产生时发送给观察者,和中介者模式的不同地方是中介者模式强调中介的作用以及中介双方的交互,观察者模式是主动调用观察者成员函数进行消息发送. 代码如下: #include &l ...

随机推荐

  1. jsp tomcat jdk版本对应

    jsp使用jdk8时,需要tomcat7以及以上版本,jsp在使用jdk7的时候,tomcat使用tomcat6即可

  2. R语言格式化数字和字符串format函数

    数字和字符串可以使用 format()函数的格式化为特定样式. 语法 format()函数的基本语法是: format(x, digits, nsmall,scientific,width,justi ...

  3. 724_Find-Pivot-Index

    目录 724_Find-Pivot-Index Description Solution Java solution Python solution 724_Find-Pivot-Index Desc ...

  4. [PY3]——内置数据结构(2)——元组及其常用操作

    定义和初始化 #tuple() 使用工厂函数tuple定义一个空元组 #() 使用圆括号定义一个空元组 #(1,2,3) 使用圆括号定义有初始值的元组 #tuple(可迭代对象) 把可迭代对象转换为一 ...

  5. 注解完成spring json返回数据格式配置

    import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.module.Simp ...

  6. Java - 使可访问性最小化

    模块设计是否良好,有个重要的因素在于,相对外部模块是否隐藏内部数据以及实现细节. 设计良好的模块会隐藏实现细节,并将API与其实现隔离开来. 模块之间通过API进行通信,对于内部工作情况互不可见. 即 ...

  7. SQL Server将DataTable传入存储过程(Table Value Parameter)

    博主在做毕业设计的时候,需要用到事务处理和多次将数据写入不同的表中,但是 SQL Server 数据库是不支持数组类型变量的,想要实现数组的功能,可以通过 XML 和数据表的方法实现,但是实现方法非常 ...

  8. ASP.NET中让图片以二进制的形式存储在数据库中

    今早有个网友问到我这问题,以前我都是直接在数据库中存文件名的,还没有试过存储整张图片到数据库中,上网搜索了一下,自己又测试了一番,代码如下:建立保存图片的表的SQL语句: USE [niunantes ...

  9. 撩课-Web大前端每天5道面试题-Day5

    1.写一个深度克隆方法(es5)? /** * 深拷贝 * @param {object}fromObj 拷贝的对象 * @param {object}toObj 目标对象 */ function d ...

  10. python 实现websocket

    python中websocket需要我们自己实现握手代码,流程是这样:服务端启动websocket服务,并监听.当客户端连接过来时,(需要我们自己实现)服务端就接收客户端的请求数据,拿到请求头,根据请 ...