定义:
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
场景:
我们有一个气象站,我们通过WeatherData获取气象站的最新数据,并更新布告板上的数据。我们定义了两个布告板,一个是温度计,显示最新的温度,另一个布告板就是显示当前的所有温度、湿度和气压的最新数据。
类图:
Observer,Subject,DisplayElement代码如下:
1 #ifndef SUBJECT_H 2 #define SUBJECT_H 3 #include4 #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 #include5 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 #include2 #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 }
运行结果: