观察者模式

定义:

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

场景:

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

类图:

Observer,Subject,DisplayElement代码如下:

 1 #ifndef SUBJECT_H
2 #define SUBJECT_H
3 #include <iostream>
4 #include <list>
5 #include <string>
6 #include <algorithm>
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 <iostream>
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<Observer*> 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<Observer*>::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<Observer*>::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<Observer*>::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 <iostream>
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 }

运行结果:




posted @ 2012-03-08 12:19  雨中枫叶  阅读(253)  评论(0编辑  收藏  举报