观察者模式定义:
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。
观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己

类图
图一 观察者模式类图
可以看出,在这个观察者模式的实现里有下面这些角色:

  1. 抽象主题(Subject)角色:主题角色把所有对观察考对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,主题角色又叫做抽象被观察者(Observable)角色,一般用一个抽象类或者一个接口实现。
  2. 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者角色一般用一个抽象类或者一个接口实现。在这个示意性的实现中,更新接口只包含一个方法(即Update()方法),这个方法叫做更新方法。
  3. 具体主题(ConcreteSubject)角色:将有关状态存入具体现察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者角色(Concrete Observable)。具体主题角色通常用一个具体子类实现。
  4. 具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体现察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体现察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。
观察者模式提供了一种对象设计,让主题和观察者之间松耦合。
当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。
关于观察者的一切,主题只知道观察者实现了某个接口(Observer)。主题不需要知道观察者的具体类是谁、做了些什么或其他任何细节。
任何时候我们可以增加新的观察者。因为主题唯一依赖的东西是一个实现Observer接口的对象列表。在有新的类型的观察者出现时,主题的代码不需要修改。所要做的就是在新的类里实现此观察者接口,然后注册为观察者即可。
改变主题或观察者其中一方,并不会影响另一方。因为两者是松耦合的。
气象站实例C++编程实现(来源于《Head First设计模式》):
其类图:
代码:
//观察者模式C++编程实现
//author:江南烟雨
//E-Mail:xiajunhust@gmail.com
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;static int setConditionTimes = 0;//记录设置的总次数//观察者(布告板)抽象接口
class Observer{
public:virtual void update(float temp,float humidity,float pressure) = 0;
};//主题抽象接口
class Subject{
public:virtual void registerObserver(Observer *o) = 0;//注册观察者virtual void removeObserver(Observer *o) = 0;//删除观察者virtual void notifyObserver() = 0;//当主题状态改变时,通知所有观察者
};//布告板显示
class DisplayElement{
public: virtual void display()= 0;
};//WeatherData具体类,继承自主题抽象类
class WeatherData:public Subject{
private:vector<Observer *> observers;float temperature;float humility;float pressure;public:WeatherData(){}~WeatherData(){vector<Observer*>::iterator pos = observers.begin();for (;pos != observers.end();++pos){delete (*pos);}}void registerObserver(Observer *o){observers.push_back(o);}void removeObserver(Observer *o){vector<Observer*>::iterator pos = find(observers.begin(),observers.end(),o);if (pos != observers.end()){observers.erase(pos);}}void notifyObserver(){vector<Observer*>::iterator pos = observers.begin();for (;pos != observers.end();++pos){(*pos)->update(temperature,humility,pressure);}}//当从气象站得到更新观测值时,通知观察者void messurementsChanged(){notifyObserver();}//设置气象站观测值void setMessurements(float temperature,float humility,float pressure){++setConditionTimes;this->temperature = temperature;this->humility = humility;this->pressure = pressure;messurementsChanged();}
};//布告板具体类:目前状况
class CurrentConditionDisplay:public Observer,public DisplayElement{
private:float temperature;float humility;Subject *weatherData;public: CurrentConditionDisplay(Subject *weatherData){this->weatherData = weatherData;weatherData->registerObserver(this);}~CurrentConditionDisplay(){}void update(float temp,float humi,float pressure){this->temperature = temp;this->humility = humi;display();}void display(){cout << "Current conditions: " << temperature << "F degrees and " <<humility << "% humility" << endl;}
};//布告板具体类:气象统计类
class WeatherStatisticsDisplay:public Observer,public DisplayElement{
private:float avgTemperatuere,maxTemperature,minTemperature;Subject *weatherData;public: WeatherStatisticsDisplay(Subject *weatherData){this->weatherData = weatherData;weatherData->registerObserver(this);}~WeatherStatisticsDisplay(){}void update(float temp,float humi,float pressure){if (1 == setConditionTimes){this->avgTemperatuere = temp;this->maxTemperature = temp;this->minTemperature = temp;}else{this->avgTemperatuere = (this->avgTemperatuere * (setConditionTimes - 1) + temp) / setConditionTimes;this->maxTemperature = this->maxTemperature > temp ? this->maxTemperature : temp;this->minTemperature = this->minTemperature < temp ? this->minTemperature : temp;}display();}void display(){cout << "Avg/Max/Min: temperature  " << avgTemperatuere << "/" << maxTemperature << "/" <<minTemperature << endl;}
};int main()
{WeatherData *weatherData = new WeatherData();CurrentConditionDisplay *currentConditionDisplay = new CurrentConditionDisplay(weatherData);WeatherStatisticsDisplay *weatherStatisticsDisplay = new WeatherStatisticsDisplay(weatherData);weatherData->setMessurements(80,65,30.4f);weatherData->setMessurements(82,70,29.2f);weatherData->setMessurements(78,90,29.2f);weatherData->removeObserver(weatherStatisticsDisplay);cout << "after remove observer WeatherStatisticsDisplay:" << endl;weatherData->setMessurements(80,65,30.4f);weatherData->setMessurements(82,70,29.2f);weatherData->setMessurements(78,90,29.2f);return 0;
}

运行结果(VS2008 + Win7):

【设计模式】设计模式C++编程实现之观察者模式(ObserverPattern)相关推荐

  1. [java设计模式简记] 观察者模式(Observer-Pattern)

    观察者模式(Observer-Pattern) 数据主体拥有需要数据的对象的数据,并且数据改变时需要数据的对象要及时知道 意图: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖 ...

  2. 各种设计模式对比及编程思想总结

    各种设计模式对比及编程思想总结: 设计模式 一句话归纳 工厂模式(Factory) 只对结果负责,不要三无产品 单例模式(Singleton) 保证独一无二 适配器模式(Adapter) 需要一个转换 ...

  3. 设计模式C++实现(15)——观察者模式

    观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.它还有两个别名,依赖(Dependents),发布-订阅(Publish-Subsr ...

  4. JavaScript设计模式之发布-订阅模式(观察者模式)-Part1

    <JavaScript设计模式与开发实践>读书笔记. 发布-订阅模式又叫观察者模式,它定义了对象之间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖它的对象都将得到通知. 例如 ...

  5. 设计模式C++实现(7)——观察者模式

    观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.它还有两个别名,依赖(Dependents),发布-订阅(Publish-Subsr ...

  6. c语言 适配器模式例子,NodeJS设计模式总结【单例模式,适配器模式,装饰模式,观察者模式】...

    NodeJS设计模式总结[单例模式,适配器模式,装饰模式,观察者模式] 发布时间:2020-08-21 03:08:03 来源:脚本之家 阅读:117 作者:lucky芬 本文实例讲述了NodeJS设 ...

  7. 聊一聊C++设计模式、函数式编程等

    文章目录 1.variant技巧 2.std::enable_if_t用法 (1)C++模板 SFINAE (2)C++模板 匿名类型参数 (3)enable_if (4)enable_if_t (5 ...

  8. 图解设计模式-设计模式七大原则

    Java设计模式 设计模式七大原则 设计模式的目的 编写软件过程中,程序员面临来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让 **程序(软件)**具有更好的 ...

  9. 设计模式 ----- 设计模式总结

    设计模式 -– 设计模式总结 设计模式系列源码: https://github.com/liloqian/DesiginModeDemo 1.什么是设计模式 模式是指在某情形下,针对某问题的某种解决方 ...

  10. Java设计模式---设计模式概述及七大原则

    网课指路:尚硅谷Java设计模式(图解+框架源码剖析)_哔哩哔哩_bilibili 设计模式介绍         1) 设计模式是程序员在面对同类软件工程设计问题所总结出来的有用的经验, 模式不是代码 ...

最新文章

  1. libuvc介绍及简单使用
  2. php hash pbkdf2,PHP hash_pbkdf2 哈希(Hash)函数
  3. 基本值类型(一):序数类型与运算符
  4. java数组的声明学号姓名线性结构_20172302 《Java软件结构与数据结构》实验一:线性结构实验报告...
  5. sql server 触发器
  6. 毕业论文计算机设计,计算机设计毕业论文
  7. 宽度学习(BLS)网络的研究和应用
  8. 吴恩达采访人工智能大师实录
  9. python爬虫大众点评字体反爬
  10. MSDC 4.3 接口规范(20)
  11. Web全栈架构师(三)——NodeJS+持久化学习笔记(2)
  12. oracle查看当前的数据库实例名称,主机名称
  13. 在12306的程序猿面前,没人敢说委屈
  14. 行业洞察 | Web3、AI4Science、机器人,热门赛道全解析...AI商业化受阻,拐点在何方?...
  15. 软件开发过程大观——软件开发过程改进为什么能帮助软件质量提升?
  16. 【博学谷学习记录】超强总结,用心分享丨前端开发:BootStrap框架基础用法
  17. 计算机毕业设计JAVA海滨体育馆管理系统mybatis+源码+调试部署+系统+数据库+lw
  18. Java开发如何在线打开Word文件
  19. python挖矿代码_python检测挖矿特征的几种方式
  20. 用迅捷CAD编辑器怎么更改文字样式

热门文章

  1. Dataloader与Dataset
  2. 01_Influxdb1.7.7的安装配置启动
  3. 保存blob为本地文件
  4. IE6的重定向页面无法跳转解决
  5. bootstrap菜单展开收起_基于bootstrap的后台左侧导航菜单和点击二级菜单刷新二级页面时候菜单展开显示当前菜单...
  6. Ubuntu系统显卡驱动、CUDA、CUDNN安装(一显卡驱动)
  7. Ubuntu 上寻找依赖库(.so)的方法
  8. bios升级工具_雨林木风U盘启动盘装系统制作工具再次升级。。。
  9. python 后10个元素_10 行 Python 代码写 1 个 USB 病毒
  10. python summary_利用python爬取新闻信息