• 观察者模式 Observer – 学习HeadFirst设计模式记录



    1、HeadFirst上的标准实现,属于教学版。

    2、参考Java内置实现,感觉更实用些。


    1、HeadFirst上的标准实现,属于教学版。

    接口声明:  

    /* 说明:

     报纸出版社 + 订阅者 = 观察者模式 

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

     设计原则:
     为了交互对象之间的松耦合设计而努力。
    */

    /**
    *  观察者,即订阅者
    */
    class Observer
    {
    public:
        virtual void Update(float temperature, float humidity, float pressure) = 0;
    };

    /**
    *  主题,相当于出版社
    */
    class Subject
    {
    public:
        virtual void RegisterObserver(Observer *observer) = 0;
        virtual void RemoveObserver(Observer *observer) = 0;
        virtual void NotifyObserver() = 0;
    };

     

    类实现:

    #include <iostream>
    #include <list>

    #include "main.h"


    class WeatherData : public Subject
    {
    public:

        WeatherData(float temperature=0float humidity=0float pressure=0) : _temperature(temperature)
                                                                             , _humidity(humidity)
                                                                             , _pressure(pressure)
        {}
        /* 管理观察者 */
        virtual void RegisterObserver(Observer *observer)
        {
            _observerList.push_back(observer);
        }
        virtual void RemoveObserver(Observer *observer)
        {
            _observerList.remove(observer);
        }
        /* 通知观察者,推送新数据 */
        virtual void NotifyObserver()
        {
            std::list<Observer*>::iterator it = _observerList.begin();
            for (; it != _observerList.end(); ++it)
            {
                (*it)->Update(_temperature, _humidity, _pressure);
            }
        }

        void SetData(float temperature, float humidity, float pressure)
        {
            _temperature = temperature;
            _humidity    = humidity;
            _pressure    = pressure;
            MeasurementsChanged();
        }
        void MeasurementsChanged()
        {
            NotifyObserver();
        }

        /* 查询接口 */
        float GetTemperature()  { return _temperature; }  
        float GetHumidity()  { return _humidity; }
        float GetPressure()  { return _pressure; }

    private:
        std::list<Observer*> _observerList;
        float _temperature;
        float _humidity;
        float _pressure;
    };

    class CurrentConditionDisplay : public Observer
    {
    public:
        CurrentConditionDisplay(Subject *weatherData) : _weatherData(weatherData)
        {
            _weatherData->RegisterObserver(this);
        }
        /* 观察者接口*/
        virtual void Update(float temperature, float humidity, float pressure)
        {
            Display(temperature, humidity, pressure);
        }
        virtual void Display(float temperature, float humidity, float pressure)
        {
            std::cout << "Current Condition : " << temperature << " degrees, " << humidity << "% humidity, " << pressure << " pa ." << std::endl;
        }

    private:
        Subject *_weatherData;
    };
    //  class StatisticsDisplay : public Observer, public DisplayElement {};
    //  class ForecastDisplay   : public Observer, public DisplayElement {};

    int main()
    {
        WeatherData weatheData;
        CurrentConditionDisplay currDisplay(&weatheData);
        weatheData.SetData(23101);

        return 0;
    }

     

    2、参考Java内置实现,感觉更实用些。

    1)将公共部分放入基类中(在Observable中管理观察者)。

    2)告知观察者数据已更新,然后由观察者主动获取自己需要的数据。

     

    接口声明:

    #include <list>

    class Observable;

    /**
    *  观察者
    */
    class Observer
    {
    public:
        /* 被观察者作为参数,因为一个观察者可以观察多个对象 */
        virtual void Update(Observable *pObs/*, Object obj*/) = 0;
    };

    /**
    *  被观察者,已实现观察者管理功能
    */
    class Observable
    {
    public:
        Observable() {}
        virtual ~Observable() {}

        void RegisterObserver(Observer *observer)
        {
            _observerList.push_back(observer);
        }
        void RemoveObserver(Observer *observer)
        {
            _observerList.remove(observer);
        }
        /* 通知观察者 */
        void NotifyObserver()
        {
            std::list<Observer*>::iterator it = _observerList.begin();
            for (; it != _observerList.end(); ++it)
            {
                (*it)->Update(this);
            }
        }

    private:
        std::list<Observer*> _observerList;
    };

    类实现:

    #include <iostream>
    #include <list>

    #include "main.h"


    class WeatherData : public Observable
    {
    public:
        
        WeatherData(float temperature=0float humidity=0float pressure=0) : _temperature(temperature)
                                                                             , _humidity(humidity)
                                                                             , _pressure(pressure)
        {}
        
        void SetData(float temperature, float humidity, float pressure)
        {
            _temperature = temperature;
            _humidity    = humidity;
            _pressure    = pressure;
            MeasurementsChanged();
        }
        void MeasurementsChanged()
        {
            NotifyObserver();
        }
        
        /* 提供查询接口 */
        float GetTemperature()  { return _temperature; }  
        float GetHumidity()  { return _humidity; }
        float GetPressure()  { return _pressure; }
        
    private:
        float _temperature;
        float _humidity;
        float _pressure;
    };


    class CurrentConditionDisplay : public Observer
    {
    public:
        CurrentConditionDisplay(Observable *weatherData) : _weatherData(weatherData)
        {
            _weatherData->RegisterObserver(this);
        }
        /* 观察者接口*/
        virtual void Update(Observable *pObs/*, Object obj*/)
        {
            WeatherData *pWeatheData =  dynamic_cast<WeatherData *>(pObs);
            if (NULL != pWeatheData)
            {/*收到通知后,主动获取数据,然后显示*/
                Display(pWeatheData->GetTemperature(), pWeatheData->GetHumidity(), pWeatheData->GetPressure());
            }
        }
        virtual void Display(float temperature, float humidity, float pressure)
        {
            std::cout << "Current Condition : " << temperature << " degrees, " << humidity << "% humidity, " << pressure << " pa ." << std::endl;
        }
        
    private:
        Observable *_weatherData;
    };
    //  class StatisticsDisplay : public Observer, public DisplayElement {};
    //  class ForecastDisplay   : public Observer, public DisplayElement {};

    int main()
    {
        WeatherData weatheData;
        CurrentConditionDisplay currDisplay(&weatheData);
        weatheData.SetData(23101);
        
        return 0;
    }
      

    VC6中,当使用dynamic_cast时,会有告警warnning,并且运行时会报错:

    warning C4541: 'dynamic_cast' used on polymorphic type 'class xxxx with /GR-; unpredictable behavior may result

    解决方法:

    工程->设置->C/C++->分类->C++语言

    选中允许RTTI

    对于typeid的使用编译时没有警告,但是运行时也有问题,同样需要选中RTTI

  • 相关阅读:
    Jenkins+gitlab自动化构建部署
    浅尝CI/CD,真香
    各种奇葩,我感觉我快窒息了,来吐吐槽...
    用SMART原则来创建一个好的OKR
    用OKR改变个人能力得不到明显提升的困境
    承诺型与愿景型,什么样的OKR适合你?
    OKR文化:关键成果必须具备的五个特点
    为什么不能完全用OKR替代KPI?
    OKR的激励方式应该注意什么?
    OKR如何与绩效考核并行?
  • 原文地址:https://www.cnblogs.com/ant-wjf/p/4529270.html
Copyright © 2020-2023  润新知