观察者模式
定义一种对象间的一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖它的对象都得到通知并自动更新。
动机
软件构造过程中,需要为某些对象创建一种“通知依赖关系” — 一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)随之改变。若此依赖关系过于紧密,则软件不能很好的抵御变化。
观察者模式能够弱化这种依赖关系,形成稳定依赖关系、解耦合。
适用场景
1、一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这些方面封装在独立的对象中使他们可以各自独立的改变和复用。
2、一个对象的改变将导致其它一个或者多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
3、一个对象必须通知其他对象,而并不知道这些对象是谁。
4、需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
优点
观察者和被观察者是抽象耦合的。
建立一套触发机制。
缺点
如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
结构图
代码
#pragma once
// ------------ 观察者模式 ---------------
#include <list>
#include <memory>
namespace ObserverPattern {
// 抽象观察者
class Observer {
public:
virtual void update() = 0;
};
// ---------------- 稳定 ----------------
class Subject {
public:
// 添加观察者
void attach(Observer* opObserver) {
mlstObserver.push_back(opObserver);
}
// 移除观察者
void detach(Observer* opObserver) {
mlstObserver.remove(opObserver);
}
// 通知所有观察者
void notify() {
for (auto observer : mlstObserver) {
observer->update(); // 更新
}
}
private:
std::list<Observer*> mlstObserver; // 观察者
};
// ---------------- 变化 ----------------
// 具体观察者1
class ConcreteObserver1 : public Observer {
public:
virtual void update() {}
};
// 具体观察者2
class ConcreteObserver2 : public Observer {
public:
virtual void update() {}
};
void test() {
Subject subject;
std::shared_ptr<ConcreteObserver1> sp_co1 = std::make_shared<ConcreteObserver1>();
std::shared_ptr<ConcreteObserver2> sp_co2 = std::make_shared<ConcreteObserver2>();
subject.attach(sp_co1.get());
subject.attach(sp_co2.get());
subject.notify();
subject.detach(sp_co1.get());
subject.detach(sp_co2.get());
}
}