一、模式核心原理
1.1 模式定义
观察者模式(Observer Pattern)是一种行为型设计模式,定义了对象间一对多的依赖关系,当一个对象(被观察者)的状态发生改变时,所有依赖于它的对象(观察者)都会自动收到通知并更新。
该模式的核心价值在于解耦被观察者与观察者:
1.2 UML 类图结构
观察者模式包含四个核心角色:
角色 |
职责 |
典型实现 |
Subject(抽象被观察者) |
定义观察者管理接口(注册 / 移除 / 通知) |
抽象基类 |
ConcreteSubject(具体被观察者) |
维护状态,状态变化时通知所有观察者 |
继承 Subject 的具体类 |
Observer(抽象观察者) |
定义更新接口,供被观察者通知时调用 |
抽象基类 |
ConcreteObserver(具体观察者) |
实现更新接口,处理被观察者的通知 |
继承 Observer 的具体类 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| +----------------+ +----------------+ | Subject |<------| Observer | +----------------+ +----------------+ | + attach() | | + update() | | + detach() | +----------------+ | + notify() | ^ +----------------+ | ^ | | | +----------------+ +----------------+ |ConcreteSubject | |ConcreteObserver| +----------------+ +----------------+ | - state | | - subject | | + getState() | | + update() | | + setState() | +----------------+ +----------------+
|
1.3 抽象观察者接口
1 2 3 4 5 6
| class Observer { public: virtual ~Observer() = default; virtual void Update(float temp, float humidity, float pressure) = 0; };
|
- 抽象类定义了统一的更新接口
- 使用虚析构函数保证多态安全
- 接口参数采用天气数据三要素(温度、湿度、气压)
1.4 抽象主题类
1 2 3 4 5 6 7
| class Subject { public: virtual void RegisterObserver(Observer* pObserver) = 0; virtual void RemoveObserver(Observer* pObserver) = 0; virtual void NotifyObservers() = 0; };
|
- 定义了观察者管理的基本操作
- 接口参数为观察者指针,支持多态调用
- 未实现具体功能,由子类完成实现
二、核心通知机制实现
2.1 具体主题实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class WeatherData : public Subject { private: std::vector<Observer*> observers; float temperature; float humidity; float pressure;
public: void RegisterObserver(Observer* pObserver) override { observers.push_back(pObserver); }
void RemoveObserver(Observer* pObserver) override { auto it = std::find(observers.begin(), observers.end(), pObserver); if (it != observers.end()) { delete *it; observers.erase(it); } }
void NotifyObservers() override { for (auto pObserver : observers) { pObserver->Update(temperature, humidity, pressure); } }
void SetMeasurements(float temp, float humidity, float pressure) { this->temperature = temp; this->humidity = humidity; this->pressure = pressure; NotifyObservers(); } };
|
- 使用vector动态存储观察者指针
- 提供安全的内存管理机制
- 暴露SetMeasurements接口用于数据更新
- 遵循《大话设计模式》中观察者与被观察者分离原则
2.2 具体观察者类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| class CurrentConditionsDisplay : public Observer { private: float temperature; float humidity;
public: void Update(float temp, float humidity, float pressure) override { temperature = temp; humidity = humidity; Display(); }
void Display() { std::cout << "当前温度: " << temperature << " 湿度: " << humidity << " 未采用气压数据\n"; } };
class StatisticsDisplay : public Observer { private: float temperature; float humidity; float pressure;
public: void Update(float temp, float humidity, float pressure) override { this->temperature = temp; this->humidity = humidity; this->pressure = pressure; Display(); }
void Display() { std::cout << "统计温度: " << temperature << " 统计湿度: " << humidity << " 统计气压: " << pressure << "\n"; } };
|
- 每个观察者独立实现Update逻辑
- 调用Display方法展示具体数据
- 参数传递遵循主题接口规范
- 所有C++类定义完整且符合规范
三、典型应用场景演示
3.1 客户端代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| int main() { WeatherData* weatherData = new WeatherData(); Observer* currentDisplay = new CurrentConditionsDisplay(); Observer* statsDisplay = new StatisticsDisplay(); weatherData->RegisterObserver(currentDisplay); weatherData->RegisterObserver(statsDisplay); weatherData->SetMeasurements(25.0, 65.0, 1013.0); delete weatherData; delete currentDisplay; delete statsDisplay; return 0; }
|
- 展现观察者模式核心流程
- 必须手动管理内存,体现传统指针特性
- 通过主题接口统一管理观察者生命周期
- 保持与《大话设计模式》中的示例一致
四、模式机制深度解析
4.1 松耦合原理
1 2 3 4 5 6
| void WeatherData::NotifyObservers() { for (auto pObserver : observers) { pObserver->Update(temperature, humidity, pressure); } }
|
- 主题与观察者通过接口解耦
- 采用多态实现动态绑定
- 业务逻辑与显示逻辑物理分离
- 支持灵活扩展:添加新观察者无需修改主题
4.2 实现细节分析
- 内存管理:逐个删除观察者指针
- 数据传递:主题接口统一传递状态数据
- 通知机制:通过for循环遍历所有观察者
- 异常处理:未直接处理移除失败的情况
4.3 与传统方式对比
传统方式 |
观察者模式 |
直接方法调用 |
接口回调机制 |
耦合度高 |
松耦合设计 |
扩展性差 |
灵活扩展 |
难以维护 |
易于维护 |
4.4 性能优化考量
- 使用vector实现动态数组
- 考虑使用智能指针可提高安全性
- 删除操作需确保观察者正确释放资源
- 多次注册同一观察者会导致重复通知