博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
观察者模式
阅读量:5248 次
发布时间:2019-06-14

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

定义:

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

场景:

我们有一个气象站,我们通过WeatherData获取气象站的最新数据,并更新布告板上的数据。我们定义了两个布告板,一个是温度计,显示最新的温度,另一个布告板就是显示当前的所有温度、湿度和气压的最新数据。

类图:

Observer,Subject,DisplayElement代码如下:

1 #ifndef SUBJECT_H  2 #define SUBJECT_H  3 #include 
4 #include
5 #include
6 #include
7 using namespace std; 8 9 class Observer; 10 11 // 主题 12 class Subject 13 {
14 public: 15 virtual void registerObserver(Observer* o) = 0; 16 virtual void removeObserver(Observer* o) = 0; 17 virtual void notifyObserver() = 0; 18 float getTemperature(); 19 float getHumidity(); 20 float getPressure(); 21 protected: 22 float m_temperature; 23 float m_humidity; 24 float m_pressure; 25 }; 26 float Subject::getTemperature() 27 {
28 return m_temperature; 29 } 30 31 float Subject::getHumidity() 32 {
33 return m_humidity; 34 } 35 36 float Subject::getPressure() 37 {
38 return m_pressure; 39 } 40 // 观察者 41 class Observer 42 {
43 public: 44 Observer(Subject* pWeaterData); 45 virtual ~Observer() {}; 46 virtual void update() = 0; 47 Subject* getWeaterData(); 48 protected: 49 Subject* m_weaterData; 50 }; 51 Observer::Observer(Subject* pWeaterData) 52 {
53 m_weaterData = pWeaterData; 54 } 55 56 Subject* Observer::getWeaterData() 57 {
58 return m_weaterData; 59 } 60 61 class DisplayElement 62 {
63 public: 64 virtual void display() = 0; 65 }; 66 #endif

WeatherData,CurrentConditionsDisplay,Thermometer代码如下:

1 #ifndef WEATHER_H   2 #define WEATHER_H   3 #include "subject.h"   4 #include 
5 class WeatherData:public Subject 6 {
7 public: 8 WeatherData(); 9 ~WeatherData(); 10 void registerObserver(Observer* o); 11 void removeObserver(Observer* o); 12 void notifyObserver(); 13 void measurementsChanged(); 14 void setMeasurements(float temperature, float humidity, float pressure); 15 private: 16 list
m_lObserver; 17 }; 18 WeatherData::WeatherData() 19 {
20 m_temperature = 0; 21 m_humidity = 0; 22 m_pressure = 0; 23 } 24 25 WeatherData::~WeatherData() 26 {
27 list
::iterator iter, temp; 28 for (iter=m_lObserver.begin(); iter!=m_lObserver.end(); ++iter) 29 {
30 delete (*iter); 31 } 32 m_lObserver.clear(); 33 } 34 35 void WeatherData::registerObserver(Observer* o) 36 {
37 m_lObserver.push_back(o); 38 } 39 40 void WeatherData::removeObserver(Observer* o) 41 {
42 list
::iterator iter; 43 44 iter = std::find(m_lObserver.begin(), m_lObserver.end(), o); 45 46 if (m_lObserver.end() != iter) 47 {
48 m_lObserver.erase(iter); 49 } 50 } 51 52 void WeatherData::notifyObserver() 53 {
54 list
::iterator iter; 55 for (iter=m_lObserver.begin(); iter!=m_lObserver.end(); ++iter) 56 {
57 (*iter)->update(); 58 } 59 } 60 61 void WeatherData::measurementsChanged() 62 {
63 notifyObserver(); 64 } 65 66 void WeatherData::setMeasurements(float temperature, float humidity, float pressure) 67 {
68 m_temperature = temperature; 69 m_humidity = humidity; 70 m_pressure = pressure; 71 measurementsChanged(); 72 } 73 74 // 当前条件显示 75 class CurrentConditionsDisplay:public Observer,public DisplayElement 76 {
77 public: 78 CurrentConditionsDisplay(Subject* pWeaterData); 79 ~CurrentConditionsDisplay(); 80 void update(); 81 void display(); 82 private: 83 float m_template; // 温度 84 float m_humidity; // 湿度 85 float m_pressure; // 气压 86 }; 87 CurrentConditionsDisplay::CurrentConditionsDisplay(Subject* pWeaterData):Observer(pWeaterData) 88 {
89 pWeaterData->registerObserver(this); 90 } 91 CurrentConditionsDisplay::~CurrentConditionsDisplay() 92 {
93 m_weaterData = NULL; 94 } 95 void CurrentConditionsDisplay::update() 96 {
97 m_template = m_weaterData->getTemperature(); 98 m_humidity = m_weaterData->getHumidity(); 99 m_pressure = m_weaterData->getPressure(); 100 display(); 101 } 102 void CurrentConditionsDisplay::display() 103 {
104 printf("Current conditions %f0.2F degrees and %0.2f%s humidity and pressure %0.2f\n",m_template,m_humidity,"%",m_pressure); 105 } 106 107 // 温度计 108 class Thermometer:public Observer,public DisplayElement 109 {
110 public: 111 Thermometer(Subject* pWeaterData); 112 ~Thermometer(); 113 void update(); 114 void display(); 115 private: 116 float m_template; // 温度 117 }; 118 Thermometer::Thermometer(Subject* pWeaterData):Observer(pWeaterData) 119 {
120 pWeaterData->registerObserver(this); 121 } 122 123 Thermometer::~Thermometer() 124 {
125 m_weaterData = NULL; 126 } 127 128 void Thermometer::update() 129 {
130 m_template = m_weaterData->getTemperature(); 131 display(); 132 } 133 134 void Thermometer::display() 135 {
136 printf("Current conditions %f0.2F degrees\n",m_template); 137 } 138 #endif

主程序:

1 #include 
2 #include "subject.h" 3 #include "weather.h" 4 int main() 5 {
6 WeatherData* pWeatherData = new WeatherData(); 7 CurrentConditionsDisplay* pCurrentConditionsDisplay = new CurrentConditionsDisplay(pWeatherData); 8 Thermometer* pThermometer = new Thermometer(pWeatherData); 9 pWeatherData->setMeasurements(123,456,789); 10 11 // 当移除观察者后,需要手动释放内存 12 pCurrentConditionsDisplay->getWeaterData()->removeObserver(pCurrentConditionsDisplay); 13 pWeatherData->setMeasurements(789,456,123); 14 15 // 当再次注册后,内存交由主题管理 16 pCurrentConditionsDisplay->getWeaterData()->registerObserver(pCurrentConditionsDisplay); 17 pWeatherData->setMeasurements(135,257,479); 18 19 delete pWeatherData; 20 return 0; 21 }

运行结果:

转载于:https://www.cnblogs.com/fengye-dream/archive/2012/03/08/2385011.html

你可能感兴趣的文章
输出n阶“魔方阵”
查看>>
学习笔记21—PS换图片背景
查看>>
electron入门心得
查看>>
格而知之2:UIView的autoresizingMask属性探究
查看>>
Spring3.0 AOP 具体解释
查看>>
我的Hook学习笔记
查看>>
EasyUI DataGrid 中字段 formatter 格式化不起作用
查看>>
海量数据存储
查看>>
js中的try/catch
查看>>
[导入]玫瑰丝巾!
查看>>
自动从网站上面下载文件 .NET把网站图片保存到本地
查看>>
【识记】 域名备案
查看>>
STL uva 11991
查看>>
MY SQL的下载和安装
查看>>
自定义OffMeshLink跳跃曲线
查看>>
寄Android开发Gradle你需要知道的知识
查看>>
简述spring中常有的几种advice?
查看>>
学习Redux之分析Redux核心代码分析
查看>>
ABAP 创建和调用WebService
查看>>
C# 实例化顺序
查看>>