观察者模式
概述
观察者模式(Observer Pattern)是一种行为型设计模式,定义了对象之间的一对多依赖关系,当一个对象(主题)的状态发生变化时,所有依赖它的对象(观察者)都会自动收到通知并更新。
本质理解
观察者模式的本质就是:被观察者调用观察者的虚函数,由观察者自己决定如何响应通知,从而实现解耦的一对多通知机制。
主题(被观察者 Subject)
- 保存所有观察者(Observer)的指针列表
- 当自身状态变化时,调用每个观察者的虚函数
update()
观察者(Observer 接口)
- 定义一个纯虚函数
update() - 所有具体观察者必须实现
update(),处理收到的通知
核心流程
主题状态改变 → 调用 notify() → 遍历所有观察者 → 调用每个观察者的 update()
notify()就是桥梁,负责把主题的变化推送给观察者update()是观察者接收通知的入口,具体行为由子类实现
代码实现(C++)
cpp
#include <iostream>
#include <vector>
using namespace std;
// -------- 观察者接口 --------
// 定义一个抽象观察者接口,所有具体观察者都必须实现 update 方法
class Observer {
public:
virtual void update(int value) = 0; // 状态更新接口,由主题调用
virtual ~Observer() = default; // 虚析构函数,保证子类对象正确销毁
};
// -------- 主题(Subject) --------
class Subject {
vector<Observer*> observers; // 保存所有注册的观察者指针
int state; // 主题的内部状态
public:
// 注册观察者
void attach(Observer* obs) {
observers.push_back(obs);
}
// 移除观察者
void detach(Observer* obs) {
// 使用 STL remove-erase idiom 删除指定观察者
observers.erase(
remove(observers.begin(), observers.end(), obs),
observers.end()
);
}
// 修改主题状态
void setState(int val) {
state = val; // 更新内部状态
notify(); // 状态变化后通知所有观察者
}
// 通知所有观察者
void notify() {
for (auto obs : observers)
obs->update(state); // 调用观察者的 update 方法
}
};
// -------- 具体观察者 --------
// 具体观察者 A
class ObserverA : public Observer {
public:
void update(int value) override {
cout << "ObserverA 收到更新,值 = " << value << endl;
}
};
// 具体观察者 B
class ObserverB : public Observer {
public:
void update(int value) override {
cout << "ObserverB 收到更新,值 = " << value << endl;
}
};
// -------- 主程序 --------
int main() {
Subject subject; // 创建主题对象
ObserverA a; // 创建具体观察者 A
ObserverB b; // 创建具体观察者 B
subject.attach(&a); // 注册观察者 A
subject.attach(&b); // 注册观察者 B
// 修改状态,自动通知所有注册观察者
subject.setState(10); // 输出 A 和 B 的 update
subject.setState(20); // 再次输出 A 和 B 的 update
return 0;
}
运行结果
ObserverA 收到更新,值 = 10
ObserverB 收到更新,值 = 10
ObserverA 收到更新,值 = 20
ObserverB 收到更新,值 = 20
核心角色
| 角色 | 说明 |
|---|---|
| Subject(主题) | 维护观察者列表,提供注册/注销接口,状态变化时通知观察者 |
| Observer(观察者) | 抽象接口,定义 update() 方法供主题调用 |
| ConcreteObserver(具体观察者) | 实现 update(),定义收到通知后的具体行为 |
设计原则
- 封装变化:将可能变化的部分(观察者列表)独立出来
- 面向接口编程:主题和观察者都通过抽象接口交互
- 松耦合:主题不需要知道观察者的具体类型
应用场景
- GUI 事件系统(如按钮点击通知多个监听器)
- MVC / MVVM 架构中的数据绑定
- 消息推送系统
- 股票行情监听
- 社交媒体关注通知
模式对比
| 对比项 | 观察者模式 | 发布-订阅模式 |
|---|---|---|
| 通信方式 | 主题直接通知观察者 | 通过消息代理中间件 |
| 耦合度 | 更紧密 | 更松散 |
| 适用场景 | 进程内 | 跨进程/跨服务 |