一、基本知识
1.定义
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。个人感觉这个跟发布订阅模式有点像。
2.要点
①观察者模式使得我们可以独立地改变目标与观察者,从而使二者之间的关系松耦合。
②观察者自己决定是否订阅通知,目标对象并不关注谁订阅了。
③观察者不要依赖通知顺序,目标对象也不知道通知顺序。
④常用在基于事件的ui框架中,也是 MVC 的组成部分。
⑤常用在分布式系统中、actor框架中;
二、结构图
三、实例演示
实例:
气象站发布气象资料给数据中心,数据中心经过处理,将气象信息更新到两个不同的显示终端(A和B)。
1.普通代码
//客户端A
class DisplayA {
public:
void Show(float temperature);
};
//客户端B
class DisplayB {
public:
void Show(float temperature);
};
//气象资料数据
class WeatherData {
};
//数据中心
class DataCenter {
public:
float CalcTemperature() {
WeatherData* data = GetWeatherData();//得到气象资料数据
float temper/*省略了对数据进行分析得到天气情况*/;
return temper;
}
private:
WeatherData* GetWeatherData(); // 不同的方式
};
int main() {
DataCenter* center = new DataCenter;
DisplayA* da = new DisplayA;
DisplayB* db = new DisplayB;
float temper = center->CalcTemperature();//从数据中心获取数据
da->Show(temper);//客户端A获取数据
db->Show(temper);//客户端B获取数据
return 0;
}
// 终端变化(增加和删除) 数据中心 不应该受终端变化的影响
2.观察者模式代码
#include <vector>
class IDisplay {
public:
virtual void Show(float temperature) = 0;
virtual ~IDisplay() {}
};
class DisplayA : public IDisplay {
public:
virtual void Show(float temperature) {};
};
class DisplayB : public IDisplay {
public:
virtual void Show(float temperature) {};
};
//气象资料
class WeatherData {
};
//数据中心分析气象资料
class DataCenter {
public:
void Attach(IDisplay* ob) {};//将客户端加入到订阅者中
void Detach(IDisplay* ob) {};//将客户端从订阅者中移除
//数据中心直接给订阅者发布消息
void Notify() {
float temper = CalcTemperature();//得到分析后的数据
//下面是直接通过订阅者调用订阅者函数,将数据传递给客户端
for (auto iter = obs.begin(); iter != obs.end(); iter++) {
(*iter)->Show(temper);
}
}
private:
virtual WeatherData* GetWeatherData() {};//获取气象资料数据
//对气象资料数据进行分析得到数据
virtual float CalcTemperature() {
WeatherData* data = GetWeatherData();
float temper/* 省略对资料数据进行分析获取*/;
return temper;
}
std::vector<IDisplay*> obs;//存放的是订阅者
};
int main() {
DataCenter* center = new DataCenter;
IDisplay* da = new DisplayA();
IDisplay* db = new DisplayB();
center->Attach(da);
center->Attach(db);
center->Notify();
//-----
center->Detach(db);
center->Notify();
return 0;
}