什么是观察者模式
对象之间存在一对多的关系,当一个对象状态发生改变时,会通知其他依赖的对象,并使他们自动更新。
举个例子
我们有一个气象站,并拥有多个种类展示板。当气象站检测到的气象数据发生改变时,展示板也进行相应的改变。
我们可以维护一个动态数组,将所有的依赖对象放到里面,状态更新函数update由依赖的类实现。当我们状态发生改变时,只要一一调用数组中的对象的update函数。为此,被依赖对象需要继承一个Subject接口,而依赖对象需要继承一个Observer接口。
我们创建一个WeatherData类,当WeatherData发生改变时,我们通知多种Display类来作出更新。
#include <iostream>
#include <vector>
#include <algorithm>
#include <typeinfo>
using namespace std;
class Observable;
// 观察者接口
class Observer{
public:
virtual void update(Observable*, void*) = 0;
};
// 被观察者接口
class Observable{
public:
vector<Observer*> ObserverArray;
// 注册观察者
virtual void RegisterObserver(Observer* Ob){ObserverArray.push_back(Ob);}
// 移除观察者
virtual void RemoveObserver(Observer* Ob){ObserverArray.erase(find(ObserverArray.begin(),ObserverArray.end(),Ob));}
// 状态改变,通知所有观察者
virtual void NotifyObserver(){
if(Changeflag){
vector<Observer*>::iterator it_begin = ObserverArray.begin();
vector<Observer*>::iterator it_end = ObserverArray.end();
for(; it_begin != it_end; it_begin++){
(*it_begin) -> update(this, (void*)this);
}
Changeflag = false;
}
}
virtual void setChange(){
Changeflag = true;
}
private:
bool Changeflag = false;
};
class WeatherData:public Observable{
private:
int temperature;
int pressure;
public:
WeatherData(int t, int p) :
temperature(t),
pressure(p)
{}
void ChangeStatus(){
setChange();
NotifyObserver();
}
int GetTemperature(){ return temperature; }
int GetPressure(){ return pressure; }
};
class Display:public Observer{
public:
Display(Observable* Ob): m_Ob(Ob){
Ob->RegisterObserver(this);
}
void show(){
cout << "temperature is " << temperature << endl;
cout << "pressure is " << pressure << endl;
}
void update(Observable* ob, void* source){
// 判断发出通知的是哪个被观察者
if(typeid(*ob) == typeid(WeatherData)){
temperature = ((WeatherData*)source) -> GetTemperature();
pressure = ((WeatherData*)source) -> GetPressure();
show();
}
}
private:
Observable* m_Ob;
int temperature = 0;
int pressure = 0;
};
int main(){
WeatherData weather(1,2);
Display myDisplay(&weather);
myDisplay.show();
weather.ChangeStatus();
}
输出结果为:
temperature is 0
pressure is 0
temperature is 1
pressure is 2
当我们的WeatherData发生状态改变时,成功通知到了其中的依赖对象。
使用观察者模式,我们可以动态地管理监听的对象,状态更新的代码也由更新方提供,被监听方不需要去关心监听方的任何实现。