定义
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(subject)的状态发生改变时,所有依赖于他的对象都得到通知并自动更新。--《设计模式》
要点
- 观察者模式使得我们可以独立地改变目标与观察者,从而使二者之间的关系松耦合;
- 观察者自己决定是否订阅通知,目标对象并不关注谁订阅了;
- 观察者不要依赖通知顺序,目标对象也不知道通知顺序;
- 常用在基于事件的ui框架中,也是MVC的组成部分;
- 常用在分布式系统中,actor框架中;
本质
触发联动
//无设计模式
class DisplayA {
public:
void Show(float temperature);
};
class DisplayB {
public:
void Show(float temperature);
};
class DisplayC {
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;
DisplayC *dc = new DisplayC;
float temper = center->CalcTemperature();
da->Show(temper);
db->Show(temper);
dc->Show(temper);
return 0;
}
// 终端变化(增加和删除) 数据中心 不应该受终端变化的影响
//采用设计模式
#include <vector>
//
class IDisplay {
public:
virtual void Show(float temperature) = 0;
virtual ~IDisplay() {}
};
class DisplayA : public IDisplay {
public:
virtual void Show(float temperature);
private:
void jianyi();
};
class DisplayB : public IDisplay{
public:
virtual void Show(float temperature);
};
class DisplayC : 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();
IDisplay *dc = new DisplayC();
center->Attach(da);
center->Attach(db);
center->Attach(dc);
center->Notify();
//-----
center->Detach(db);
center->Notify();
return 0;
}