一、模式核心原理

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); // 温度25度,湿度65%,气压1013hPa

// 通知完成,手动删除对象
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实现动态数组
  • 考虑使用智能指针可提高安全性
  • 删除操作需确保观察者正确释放资源
  • 多次注册同一观察者会导致重复通知