观察者模式包含两个对象,一个是观察者,一个是被观察者。一般而言,观察者可以有多个,被观察者只有1个。当被观察者有任何的状态变化时,会通知到所有的观察者,观察者根据状态的不同做出不同的行为。
在 GoF 4 人编写的《设计模式》中对观察者模式给出下面一个例子:
例如在 Excel 中,当数据发生变化时,柱状图、饼状图等等对象都会发生变化。即:被观察者为数据,而观察者为柱状图、饼状图这些对象。
从这个例子,我们可以理解到,当我们面向对象编码时,当一个对象的变化需要其他的对象同时改变时,使用观察者模型进行编码,代码逻辑将会变得很清晰。
#include <iostream> #include <set> using namespace std; class Observer { public: virtual void update() = 0; }; class Subject { public: // 注册观察者 void attach(Observer *observer) { m_observers.insert(observer); } // 移除观察者 void detach(Observer *observer) { m_observers.erase(observer); } // 通知函数 void notify() { cout << "被观察者状态发生变化..." << endl; for(Observer * observer : m_observers) { observer->update(); } } ~Subject() { for (Observer* observer : m_observers) { delete observer; } } private: set<Observer*> m_observers; }; // 定义具体观察者 class Observer1 : public Observer { public: void update() { cout << "Observer1 更新行为" << endl; } void play() { cout << "Observer1 其他行为" << endl; } }; class Observer2 : public Observer { public: void update() { cout << "Observer2 更新行为" << endl; } void speak() { cout << "Observer2 其他行为" << endl; } }; void test() { // 实例化观察者 Observer* ob1 = new Observer1; Observer* ob2 = new Observer2; // 实例化被观察者 Subject subject; subject.attach(ob1); subject.attach(ob2); // 假设:被观察者状态发生变化,开始通知观察者 // 观察者做出相应的动作行为 subject.notify(); } int main() { test(); return 0; }
上述示例代码中,我们只对观察者进行了抽象。当然也可以对被观察者进行抽象。另外,当被观察者状态发生变化时,也可以通过 update 函数将状态码通知给具体的观察者,观察者根据具体的状态来做出更加复杂的行为。