博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【设计模式】设计模式C++编程实现之观察者模式(ObserverPattern)
阅读量:6544 次
发布时间:2019-06-24

本文共 4773 字,大约阅读时间需要 15 分钟。

观察者模式定义:
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。
观察者模式又叫做发布-订阅(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 
#include
#include
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
observers; float temperature; float humility; float pressure;public: WeatherData(){} ~WeatherData(){ vector
::iterator pos = observers.begin(); for (;pos != observers.end();++pos) { delete (*pos); } } void registerObserver(Observer *o){ observers.push_back(o); } void removeObserver(Observer *o){ vector
::iterator pos = find(observers.begin(), observers.end(),o); if (pos != observers.end()) { observers.erase(pos); } } void notifyObserver() { vector
::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 << "/" <
<< 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):

转载地址:http://orodo.baihongyu.com/

你可能感兴趣的文章
Spring AOP 之二:Pointcut注解表达式
查看>>
在普通台式机上搭建服务器虚拟化架构Esxi平台
查看>>
电话线路 30B+D 名词解释
查看>>
python字典嵌套字典实例
查看>>
吉炬消费系统软件输入密码后无法打开软件界面故障处理
查看>>
Hibernate学习系列————注解一对多双向实例
查看>>
Cannot load from mysql.proc
查看>>
网络运维之 EX4200消除var分区使用过高的告警
查看>>
【最好的流程是没有流程】
查看>>
Apache Thrift 教程
查看>>
Python Epoll
查看>>
AS3歌词同步详解
查看>>
单例模式
查看>>
Linux环境NetBeans字体通用抗据齿解决方法
查看>>
Eclipse的花括号(brace)的输入偏好问题
查看>>
Android开发 获取当前activity的屏幕截图
查看>>
工作记录
查看>>
python之重写父类方法
查看>>
cucumber-api安装与试用
查看>>
计算硬件简史
查看>>