观察者模式
定义
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有
依赖于它的对象都得到通知并自动更新。 ——《 设计模式》 GoF
背景
气象站发布气象资料给数据中心,数据中心经过处理,将气象信息更新到两个不同的显示终端(A
和B);
代码observer1
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; } // 终端变化(增加和删除) 数据中心 不应该受终端变化的影响
代码observer2
#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) {obs.push_back(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; }
要点
- 观察者模式使得我们可以独立地改变目标与观察者,从而使二者之间的关系松耦合;
- 观察者自己决定是否订阅通知,目标对象并不关注谁订阅了;
- 观察者不要依赖通知顺序,目标对象也不知道通知顺序;
- 常使用在基于事件的ui框架中,也是MVC的组成部分;
- 常使用在分布式系统中,actor框架中;
本质
- 触发联动;
结构图
图片: