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;
};
报纸出版社 + 订阅者 = 观察者模式
定义:
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
设计原则:
为了交互对象之间的松耦合设计而努力。
*/
/**
* 观察者,即订阅者
*/
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=0, float humidity=0, float 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(23, 10, 1);
return 0;
}
#include <list>
#include "main.h"
class WeatherData : public Subject
{
public:
WeatherData(float temperature=0, float humidity=0, float 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(23, 10, 1);
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;
};
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=0, float humidity=0, float 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(23, 10, 1);
return 0;
}
#include <list>
#include "main.h"
class WeatherData : public Observable
{
public:
WeatherData(float temperature=0, float humidity=0, float 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(23, 10, 1);
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。