深入解析观察者模式:构建灵活的对象通知机制
一、模式思想与核心价值
观察者模式(Observer)是一种行为型设计模式,它建立了对象间的一对多依赖关系。当被观察对象(Subject)状态发生变化时,它会自动通知所有观察者(Observer)对象,形成松耦合的交互机制。这种模式的核心价值体现在:
- 解耦原则:分离观察者与被观察者的具体实现
- 动态订阅:支持运行时添加/移除观察者
- 事件驱动:建立高效的状态变更通知机制
- 广播通信:实现一对多的消息传递模式
二、模式结构与组件分析
核心角色:
-
Subject(目标)
- 维护观察者列表
- 提供订阅/取消订阅接口
- 通知观察者的方法
-
Observer(观察者)
- 定义更新接口
- 接收Subject状态变更通知
-
ConcreteSubject(具体目标)
- 存储具体状态信息
- 状态改变时触发通知
-
ConcreteObserver(具体观察者)
- 实现更新逻辑
- 维护与Subject的引用
三、C++实现示例:气象监测系统
传统实现版本
#include <algorithm>
#include <iostream>
#include <vector>
// 前置声明
class Observer;
// Subject接口
class WeatherData {
public:
virtual void registerObserver(Observer* o) = 0;
virtual void removeObserver(Observer* o) = 0;
virtual void notifyObservers() = 0;
virtual ~WeatherData() = default;
};
// Observer接口
class Observer {
public:
virtual void update(float temp, float humidity, float pressure) = 0;
virtual ~Observer() = default;
};
// 具体Subject实现
class ConcreteWeatherData : public WeatherData {
private:
std::vector<Observer*> observers;
float temperature;
float humidity;
float pressure;
public:
void registerObserver(Observer* o) override {
observers.push_back(o);
}
void removeObserver(Observer* o) override {
observers.erase(std::remove(observers.begin(), observers.end(), o), observers.end());
}
void notifyObservers() override {
for (auto& obs : observers) {
obs->update(temperature, humidity, pressure);
}
}
void measurementsChanged() {
notifyObservers();
}
void setMeasurements(float temp, float humidity, float pressure) {
this->temperature = temp;
this->humidity = humidity;
this->pressure = pressure;
measurementsChanged();
}
};
// 具体Observer实现
class CurrentConditionsDisplay : public Observer {
private:
float temperature;
float humidity;
WeatherData* weatherData;
public:
explicit CurrentConditionsDisplay(WeatherData* wd) : weatherData(wd) {
weatherData->registerObserver(this);
}
void update(float temp, float humidity, float pressure) override {
this->temperature = temp;
this->humidity = humidity;
display();
}
void display() const {
std::cout << "Current conditions: " << temperature << "°C and " << humidity
<< "% humidity
";
}
~CurrentConditionsDisplay() {
weatherData->removeObserver(this);
}
};
// 使用示例
int main() {
ConcreteWeatherData weatherData;
CurrentConditionsDisplay currentDisplay(&weatherData);
weatherData.setMeasurements(25.5, 65, 1013.2);
weatherData.setMeasurements(26.8, 70, 1012.8);
return 0;
}
运行结果
Current conditions: 25.5°C and 65% humidity
Current conditions: 26.8°C and 70% humidity
现代C++改进版本(使用智能指针)
#include <algorithm>
#include <memory>
#include <vector>
class Observer;
class WeatherData {
public:
virtual void registerObserver(std::shared_ptr<Observer> o) = 0;
virtual void removeObserver(std::shared_ptr<Observer> o) = 0;
virtual void notifyObservers() = 0;
virtual ~WeatherData() = default;
};
class Observer : public std::enable_shared_from_this<Observer> {
public:
virtual void update(float temp, float humidity, float pressure) = 0;
virtual ~Observer() = default;
};
class ConcreteWeatherData : public WeatherData {
private:
std::vector<std::shared_ptr<Observer>> observers;
// ...其他成员相同
float temperature;
float humidity;
float pressure;
public:
void registerObserver(std::shared_ptr<Observer> o) override {
observers.push_back(o);
}
void removeObserver(std::shared_ptr<Observer> o) override {
observers.erase(std::remove(observers.begin(), observers.end(), o), observers.end());
}
// ...其他实现相同
void notifyObservers() override {
for (auto& obs : observers) {
obs->update(temperature, humidity, pressure);
}
}
void measurementsChanged() {
notifyObservers();
}
void setMeasurements(float temp, float humidity, float pressure) {
this->temperature = temp;
this->humidity = humidity;
this->pressure = pressure;
measurementsChanged();
}
};
class CurrentConditionsDisplay : public Observer {
private:
std::weak_ptr<WeatherData> weatherData;
float temperature;
float humidity;
// ...其他成员相同
public:
explicit CurrentConditionsDisplay(std::shared_ptr<WeatherData> wd) : weatherData(wd) {}
/**
* CurrentConditionsDisplay 对象时,shared_from_this() 被调用,而此时 shared_ptr
* 尚未完全构建。为了避免这个问题,可以在构造函数中使用 std::enable_shared_from_this 的 shared_from_this()
* 方法之前确保对象已经被 shared_ptr 管理。
*/
void init() {
if (auto w = weatherData.lock()) {
w->registerObserver(shared_from_this());
}
}
void update(float temp, float humidity, float pressure) override {
this->temperature = temp;
this->humidity = humidity;
display();
}
void display() const {
std::cout << "Current conditions: " << temperature << "°C and " << humidity << "% humidity" << std::endl;
}
~CurrentConditionsDisplay() {
if (auto w = weatherData.lock()) {
w->removeObserver(shared_from_this());
}
}
};
main.cc:
#include <iostream>
#include <memory>
#include "modern_observer.h"
int main() {
// 创建 WeatherData 对象
std::shared_ptr<ConcreteWeatherData> weatherData = std::make_shared<ConcreteWeatherData>();
// 创建观察者
auto currentDisplay = std::make_shared<CurrentConditionsDisplay>(weatherData);
currentDisplay->init();
// 模拟新的天气数据
weatherData->setMeasurements(25.0f, 65.0f, 1013.0f);
weatherData->setMeasurements(27.0f, 70.0f, 1012.0f);
weatherData->setMeasurements(23.0f, 90.0f, 1011.0f);
return 0;
}
运行结果:
Current conditions: 25°C and 65% humidity
Current conditions: 27°C and 70% humidity
Current conditions: 23°C and 90% humidity
四、应用场景与最佳实践
典型应用场景
- GUI事件处理系统
- 股票价格变动通知
- 游戏引擎中的成就系统
- 分布式系统的状态同步
- 实时数据监控平台
实现注意事项
- 线程安全:多线程环境下的同步控制
- 通知策略:推模式 vs 拉模式
- 生命周期管理:防止悬空指针/引用
- 性能优化:批量通知与异步处理
- 循环依赖:避免观察链形成闭环
五、模式优劣分析
优势:
- 符合开闭原则:易于新增观察者
- 运行时动态建立对象关系
- 抽象耦合降低系统依赖性
- 支持广播通信机制
局限:
- 通知顺序不可控
- 过度使用可能导致性能问题
- 需要维护观察者列表
- 调试复杂度增加
六、扩展与变体
- 事件总线模式:集中式的事件管理
- 反应式编程:基于数据流的观察者模式
- 委托机制:C#等语言的委托实现
- 发布-订阅模式:解耦程度更高的变体
通过本文的详细讲解和代码示例,读者可以深入理解观察者模式的核心思想,掌握其在C++中的实现方法。该模式在需要建立对象间动态、松耦合关系的场景中具有重要价值,合理运用可以显著提升系统的灵活性和可维护性。后续文章我们将继续探讨其他设计模式的实现与应用。