定义
观察者模式是一种行为型设计模式,它定义了对象之间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
解决问题
稳定点:“一” 对 “多”的依赖关系,“一” 变化 “多” 跟着变
变化点:“多” 增加或者减少
C++ 观察者模式可以用于解决对象之间的依赖关系问题。该模式允许多个对象同时观察一个主题对象,并在主题对象状态发生改变时自动接收通知。
通过使用观察者模式,我们可以实现松耦合的设计,从而使得主题对象和观察者对象之间的关系更加清晰和易于维护。当主题对象发生改变时,观察者对象可以自动更新自己的状态,而不需要主题对象直接通知观察者对象。
代码结构
在 C++ 中实现观察者模式,可以定义一个抽象类 Subject,它包含了添加观察者、删除观察者和通知观察者等方法接口。
然后定义一个具体的 Subject 类,继承自抽象类 Subject,实现其中的添加观察者、删除观察者与 Notify 方法。
接着定义一个抽象的 Observer 类,它包含了一个 Update 方法,用于在收到通知后进行更新操作。
最后,定义一个具体的 Observer 类,继承自抽象类 Observer,实现其中的 Update 方法,用于在收到通知后进行具体的更新操作。
设计原则
单一职责原则(SRP):观察者模式中的主题对象和观察者对象各自承担不同的职责。主题对象负责维护状态并通知观察者,而观察者对象负责处理通知并更新自身状态。这样可以使对象的职责更加清晰,更容易理解和维护。
开闭原则(OCP):通过使用观察者模式,我们可以将主题对象和观察者对象解耦,从而使得我们可以在不修改现有代码的情况下增加新的观察者对象或修改主题对象的实现。这符合开闭原则的要求,使得我们的代码更加灵活和可扩展。
依赖倒置原则(DIP):观察者模式中的主题对象和观察者对象之间是松耦合的,它们之间的依赖关系是通过抽象接口实现的。这使得我们可以更容易地替换不同的观察者对象,同时也可以更容易地修改主题对象的实现。
迪米特法则(LoD):观察者模式中的主题对象只与抽象观察者对象通信,而不需要知道具体观察者对象的实现。这符合迪米特法则的要求,使得对象之间的耦合更加松散,降低了系统的复杂度。
如何扩展
继承实现接口
调用 attach、detach
案例
气象站发布气象资料给数据中心,数据中心经过处理,将气象信息更新到两个不同的显示终端(A 和B。。。);
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:
DataCenter (): data_(0){}
void TempNotify()
{
DisplayA *da = new DisplayA;
DisplayB *db = new DisplayB;
DisplayC *dc = new DisplayC;
float temper = this->CalcTemperature();
da->Show(temper);
db->Show(temper);
dc->Show(temper);
dc->Show(temper);
}
void SetDate(float data)
{
data_ = data;
TempNotify();
}
private:
float data_;
};
float CalcTemperature()
{
WeatherData * data = new WeatherData ();
float temper;
delete data ;
data = nullptr;
return temper;
}
int main() {
DataCenter *center = new DataCenter;
center->SetDate(CalcTemperature());
return 0;
}
如果想要新增终端,需要在DataCenter 中新建终端对象,
基于观察者模式,改进后:
#include <list>
#include <algorithm>
using namespace std;
class IDisplay {
public:
virtual void Show(float temperature) = 0;
virtual ~IDisplay() {}
};
class DisplayA : public IDisplay {
public:
virtual void Show(float temperature) {
cout << "DisplayA Show" << endl;
}
private:
void jianyi();
};
class DisplayB : public IDisplay{
public:
virtual void Show(float temperature) {
cout << "DisplayB Show" << endl;
}
};
class DisplayC : public IDisplay{
public:
virtual void Show(float temperature) {
cout << "DisplayC Show" << endl;
}
};
class DisplayD : public IDisplay{
public:
virtual void Show(float temperature) {
cout << "DisplayC Show" << endl;
}
};
class WeatherData {};
class Center{
public:
virtual void Attach(IDisplay* observer) = 0;
virtual void Detach(IDisplay* observer) = 0;
virtual void Notify() = 0;
};
class DataCenter : public Center
{
public:
void Attach(IDisplay * ob) override {
void Detach(IDisplay * ob) override {
void Notify() override
{
for (auto iter : obs) {
iter.Show(data_);
}
}
void SetDate(float data)
{
data_ = data;
Notify();
}
private:
float data_
std::list<IDisplay*> obs;
};
float CalcTemperature()
{
WeatherData * data = new WeatherData ();
float temper;
delete data ;
data = nullptr;
return temper;
}
int main() {
DataCenter *center = new DataCenter;
IDisplay *da = new DisplayA();
center->Attach(da);
IDisplay *db = new DisplayB();
center->Attach(db);
IDisplay *dc = new DisplayC();
center->Attach(dc);
center->SetDate(CalcTemperature());
center->Detach(db);
center->SetDate(CalcTemperature());
center->Attach(dd);
center->SetDate(CalcTemperature());
return 0;
}