观察者模式 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

 

posted on 2015-05-25 23:12  Waaaaaall-E  阅读(175)  评论(0编辑  收藏  举报

导航