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=
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;
};
类实现:
#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;
}
在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。