设计模式之观察者模式

来源:互联网 发布:php 读取docx中的图片 编辑:程序博客网 时间:2024/04/27 05:03
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. using namespace std;
  5. // 预声明观察者接口类
  6. class Observer;
  7. // 可观察者接口类
  8. class Observable
  9. {
  10. private:
  11.     bool m_bChanged;
  12.     vector<Observer*> m_vecObsever; // 这里暂时假设不存在重复的观察者
  13. public:
  14.     // 默认构造函数
  15.     Observable():m_bChanged(false),m_vecObsever(){}
  16.     // 纯虚析构函数
  17.     virtual ~Observable() = 0{}
  18.     // 添加观察者
  19.     void AddObserver(Observer *pObserver)
  20.     {
  21.         vector<Observer*>::const_iterator citer = find(m_vecObsever.begin(), m_vecObsever.end(), pObserver);
  22.         if (citer == m_vecObsever.end())
  23.         {
  24.             m_vecObsever.push_back(pObserver);
  25.         }
  26.     }
  27.     // 删除观察者
  28.     void DeleteObserver(Observer *pObserver)
  29.     {
  30.         vector<Observer*>::const_iterator citer = find(m_vecObsever.begin(), m_vecObsever.end(), pObserver);
  31.         if (citer != m_vecObsever.end())
  32.         {
  33.             m_vecObsever.erase(citer);
  34.         }
  35.     }
  36.     // 通知所有观察者
  37.     void NotifyObservers();
  38.     // 设置状态改变的标志
  39.     void SetChange()
  40.     {
  41.         m_bChanged = true;
  42.     }
  43. };
  44. // 天气数据主题类
  45. class WeatherData:public Observable
  46. {
  47. private:
  48.     float m_fTemperature;
  49.     float m_fHumidity;
  50.     float m_fPressure;
  51. public:
  52.     // 默认构造函数
  53.     WeatherData():m_fTemperature(0.0f),m_fHumidity(0.0f),m_fPressure(0.0f){}
  54.     // 改变测量的参数
  55.     void MeasureChange(float p_fTemperature, float p_fHumidity, float p_fPressure)
  56.     {
  57.         m_fTemperature = p_fTemperature;
  58.         m_fHumidity = p_fHumidity;
  59.         m_fPressure = p_fPressure;
  60.         SetChange();
  61.         NotifyObservers();
  62.     }
  63.     // Getter函数
  64.     float GetTemperature() const
  65.     {
  66.         return m_fTemperature;
  67.     }
  68.     
  69.     float GetHumidity() const
  70.     {
  71.         return m_fHumidity;
  72.     }
  73.     float GetPressure() const
  74.     {
  75.         return m_fPressure;
  76.     }
  77. };
  78. // 观察者接口类
  79. class Observer
  80. {
  81. protected:
  82.     Observable *m_pObservable;
  83. public:
  84.     // 默认构造函数
  85.     Observer(Observable *p_pObservable):m_pObservable(p_pObservable)
  86.     {
  87.         m_pObservable->AddObserver(this);   // 注册此观察者
  88.     }
  89.     // 纯虚析构函数
  90.     virtual ~Observer() = 0
  91.     {
  92.         if (m_pObservable != NULL)
  93.         {
  94.             m_pObservable->DeleteObserver(this);    // 注销此观察者
  95.         }
  96.     }
  97.     // 更新
  98.     virtual void Update() = 0;
  99.     // 显示
  100.     virtual void Display() const = 0;
  101. };
  102. // 通知所有观察者
  103. void Observable::NotifyObservers()
  104. {
  105.     if (m_bChanged)
  106.     {
  107.         for (size_t i = 0; i < m_vecObsever.size(); ++i)
  108.         {
  109.             m_vecObsever[i]->Update();
  110.         }
  111.         m_bChanged = false;
  112.     }
  113. }
  114. // 温度公告板
  115. class TemperatureBoard:public Observer
  116. {
  117. private:
  118.         
  119.     float m_fTemperature;
  120. public:
  121.     // 默认构造函数
  122.     TemperatureBoard(Observable *p_pObservable):Observer(p_pObservable),m_fTemperature(0.0f){}
  123.     // 更新
  124.     virtual void Update()
  125.     {
  126.         m_fTemperature = (dynamic_cast<WeatherData*> (m_pObservable))->GetTemperature();
  127.         Display();
  128.     }
  129.     // 显示
  130.     virtual void Display() const
  131.     {
  132.         cout << "Current temperature is " << m_fTemperature << "." << endl;
  133.     }
  134. };
  135. // 湿度公告板
  136. class HumidityBoard:public Observer
  137. {
  138. private:
  139.     float m_fHumidity;
  140. public:
  141.     // 默认构造函数
  142.     HumidityBoard(Observable *p_pObservable):Observer(p_pObservable),m_fHumidity(0.0f){}
  143.     // 更新
  144.     virtual void Update()
  145.     {
  146.         m_fHumidity = (dynamic_cast<WeatherData*> (m_pObservable))->GetHumidity();
  147.         Display();
  148.     }
  149.     // 显示
  150.     virtual void Display() const
  151.     {
  152.         cout << "Current humidity is " << m_fHumidity << "." << endl;
  153.     }
  154. };
  155. // 压力公告板
  156. class PressureBoard:public Observer
  157. {
  158. private:
  159.     float m_fPressure;
  160. public:
  161.     // 默认构造函数
  162.     PressureBoard(Observable *p_pObservable):Observer(p_pObservable),m_fPressure(0.0f){}
  163.     // 更新
  164.     virtual void Update()
  165.     {
  166.         m_fPressure = (dynamic_cast<WeatherData*> (m_pObservable))->GetPressure();
  167.         Display();
  168.     }
  169.     // 显示
  170.     virtual void Display() const
  171.     {
  172.         cout << "Current pressure is " << m_fPressure << "." << endl;
  173.     }
  174. };
  175. int main()
  176. {
  177.     // 当前天气数据
  178.     WeatherData weatherData;
  179.     // 公告板
  180.     TemperatureBoard temperatureBoard(&weatherData);
  181.     HumidityBoard humidityBoard(&weatherData);
  182.     PressureBoard pressureBoard(&weatherData);
  183.     weatherData.MeasureChange(23.0f, 80.0f, 60.0f);
  184.     // 注销压力观察者
  185.     weatherData.DeleteObserver(&pressureBoard);
  186.     weatherData.MeasureChange(35.0f, 76.0f, 45.0f);
  187.     system("pause");
  188.     return 0;
  189. }

对观察者模式的理解:采样针对接口编程的思想保证可观察者和观察者之间的松藕合性,

并使得任何一方的改动都不会导致另一方代码的改变;利用观察者响应接口的一致性和

OO的多态性保证双方都具有很好可移植性.对于可观察者向观察者传递数据方面,可以有

"拉"和"推"两种方式.若使用"拉"的方式,这样可以让各类观察者根据自己的需要各取所需,
但是同时也削弱了可观察者的封装性并在每次扩展可观察者类时都需要添加Getter代码;
而如果采样"推"的方式,则可避免削弱了可观察者的封装性的缺点,虽然概念上传递了所有

状态值,但由于这通常以引用或指针传递方式发生,所以并不带来效率的降低.在本示例程序

中只实现了"拉"的方式.

原创粉丝点击