1.观察者模式定义
定义对象间的⼀种⼀对多(变化)的依赖关系,以便当⼀个对象(Subject)的状态发⽣改变时,所有依赖于它的对象都得到通知并⾃动更新。
2.观察者模式遵循的模式设计原则
3.要点
a.观察者模式使得我们可以独⽴地改变⽬标与观察者,从⽽使⼆者之间的关系松耦合;
b.观察者⾃⼰决定是否订阅通知,⽬标对象并不关注谁订阅了;
c.观察者不要依赖通知顺序,⽬标对象也不知道通知顺序;
d.常使⽤在基于事件的ui框架中,也是MVC的组成部分;
e.常使⽤在分布式系统中,actor框架中;
4.本质
触发联动;
5.举例
⽓象站发布⽓象资料给数据中⼼,数据中⼼经过处理,将⽓象信息更新到两个不同的显示终端(A和B);
5.1 传统方式实现
class DisplayA {
public:
void Show(float temperature);
};
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);
db->Show(temper);
return 0;
}
// 终端变化(增加和删除) 数据中心 不应该受终端变化的影响
5.2 使用观察者模式实现
#include <vector>
class IDisplay {
public:
virtual void Show(float temperature) = 0;
virtual ~IDisplay() {}
};
class DisplayA : public IDisplay {
public:
virtual void Show(float temperature);
//类中可以有其他的接口实现,而数据中心的Notify只使用Show的接口,从而实现了数据中心的业务逻辑和数据结构的分隔。
};
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;
}