C++20观察者模式:现代化实现指南
观察者模式的核心概念
观察者模式(Observer Pattern)是一种行为型设计模式,允许对象(观察者)订阅另一个对象(被观察者)的状态变化。当被观察者的状态发生改变时,所有注册的观察者会自动收到通知并更新。该模式解耦了观察者和被观察者,符合开放-封闭原则。
C++20 中的实现改进
C++20 引入了 std::observer_ptr(草案阶段)和 std::signal(未正式纳入)等概念,但核心实现仍依赖传统模式。以下为基于 C++20 特性的现代化实现:
#include <iostream>
#include <vector>
#include <functional>
#include <memory>
template <typename... Args>
class Subject {
public:
using Callback = std::function<void(Args...)>;
void attach(Callback callback) {
observers_.push_back(callback);
}
void notify(Args... args) {
for (const auto& observer : observers_) {
observer(args...);
}
}
private:
std::vector<Callback> observers_;
};
关键组件解析
被观察者(Subject)
- 维护一个观察者列表(
std::vector<Callback>)。 - 提供
attach方法注册观察者(使用std::function存储回调)。 - 通过
notify触发所有观察者的更新(支持可变模板参数传递数据)。
观察者(Observer)
- 实现为函数对象、Lambda 或成员函数,通过
std::function统一封装。 - 避免继承带来的耦合,符合现代 C++ 的泛型编程思想。
应用场景与优势
典型场景
- GUI 事件处理(如按钮点击通知多个控件)。
- 实时数据监控(股票价格变化触发报警和日志)。
- 游戏开发(角色状态变化更新 UI 和 AI)。
C++20 优化点
- 使用
std::function替代虚函数,减少运行时开销。 - 结合
std::shared_ptr自动管理观察者生命周期。 - 通过模板支持类型安全的通知参数传递。
完整示例代码
以下示例展示温度传感器通知多个显示器的场景:
class TemperatureDisplay {
public:
void update(float temp) {
std::cout << "Display updated: " << temp << "°C\n";
}
};
int main() {
Subject<float> sensor;
TemperatureDisplay display1, display2;
sensor.attach([&display1](float temp) { display1.update(temp); });
sensor.attach([&display2](float temp) { display2.update(temp); });
sensor.notify(23.5f); // 触发所有观察者更新
return 0;
}
与其他模式的对比
与发布-订阅模式区别
- 观察者模式:直接通信,观察者与被观察者相互知晓。
- 发布-订阅模式:通过消息队列解耦,发布者和订阅者无需知道对方存在。
与中介者模式协同
- 中介者模式集中处理对象间通信,可结合观察者模式实现事件转发。
性能与线程安全
优化建议
- 使用
std::list或std::forward_list减少动态数组扩容开销。 - 通过
std::weak_ptr避免循环引用。
线程安全扩展
#include <mutex>
template <typename... Args>
class ThreadSafeSubject : public Subject<Args...> {
public:
void attach(typename Subject<Args...>::Callback callback) {
std::lock_guard<std::mutex> lock(mutex_);
Subject<Args...>::attach(callback);
}
void notify(Args... args) {
std::lock_guard<std::mutex> lock(mutex_);
Subject<Args...>::notify(args...);
}
private:
std::mutex mutex_;
};
BbS.okane387.info/PoSt/1121_943756.HtM
BbS.okane388.info/PoSt/1121_472739.HtM
BbS.okane390.info/PoSt/1121_896022.HtM
BbS.okane391.info/PoSt/1121_309856.HtM
BbS.okane392.info/PoSt/1121_102318.HtM
BbS.okane393.info/PoSt/1121_007296.HtM
BbS.okane394.info/PoSt/1121_627153.HtM
BbS.okane395.info/PoSt/1121_328962.HtM
BbS.okane396.info/PoSt/1121_626339.HtM
BbS.okane397.info/PoSt/1121_007108.HtM
BbS.okane387.info/PoSt/1121_676679.HtM
BbS.okane388.info/PoSt/1121_970952.HtM
BbS.okane390.info/PoSt/1121_772174.HtM
BbS.okane391.info/PoSt/1121_941365.HtM
BbS.okane392.info/PoSt/1121_534047.HtM
BbS.okane393.info/PoSt/1121_546186.HtM
BbS.okane394.info/PoSt/1121_840442.HtM
BbS.okane395.info/PoSt/1121_310833.HtM
BbS.okane396.info/PoSt/1121_607533.HtM
BbS.okane397.info/PoSt/1121_540917.HtM
BbS.okane398.info/PoSt/1121_128137.HtM
BbS.okane399.info/PoSt/1121_990414.HtM
BbS.okane400.info/PoSt/1121_870904.HtM
BbS.okane401.info/PoSt/1121_239095.HtM
BbS.okane402.info/PoSt/1121_279650.HtM
BbS.okane403.info/PoSt/1121_019957.HtM
BbS.okane404.info/PoSt/1121_543974.HtM
BbS.okane405.info/PoSt/1121_462322.HtM
BbS.okane406.info/PoSt/1121_078741.HtM
BbS.okane407.info/PoSt/1121_032883.HtM
BbS.okane398.info/PoSt/1121_030068.HtM
BbS.okane399.info/PoSt/1121_793587.HtM
BbS.okane400.info/PoSt/1121_152090.HtM
BbS.okane401.info/PoSt/1121_026916.HtM
BbS.okane402.info/PoSt/1121_068893.HtM
BbS.okane403.info/PoSt/1121_121932.HtM
BbS.okane404.info/PoSt/1121_259982.HtM
BbS.okane405.info/PoSt/1121_510945.HtM
BbS.okane406.info/PoSt/1121_421569.HtM
BbS.okane407.info/PoSt/1121_606600.HtM
BbS.okane398.info/PoSt/1121_458573.HtM
BbS.okane399.info/PoSt/1121_499726.HtM
BbS.okane400.info/PoSt/1121_320421.HtM
BbS.okane401.info/PoSt/1121_675655.HtM
BbS.okane402.info/PoSt/1121_136106.HtM
BbS.okane403.info/PoSt/1121_004318.HtM
BbS.okane404.info/PoSt/1121_832597.HtM
BbS.okane405.info/PoSt/1121_674350.HtM
BbS.okane406.info/PoSt/1121_144081.HtM
BbS.okane407.info/PoSt/1121_778171.HtM
BbS.okane398.info/PoSt/1121_015630.HtM
BbS.okane399.info/PoSt/1121_552272.HtM
BbS.okane400.info/PoSt/1121_083977.HtM
BbS.okane401.info/PoSt/1121_261110.HtM
BbS.okane402.info/PoSt/1121_774783.HtM
BbS.okane403.info/PoSt/1121_685886.HtM
BbS.okane404.info/PoSt/1121_703676.HtM
BbS.okane405.info/PoSt/1121_418765.HtM
BbS.okane406.info/PoSt/1121_270581.HtM
BbS.okane407.info/PoSt/1121_834628.HtM
BbS.okane398.info/PoSt/1121_261871.HtM
BbS.okane399.info/PoSt/1121_701216.HtM
BbS.okane400.info/PoSt/1121_417674.HtM
BbS.okane401.info/PoSt/1121_291275.HtM
BbS.okane402.info/PoSt/1121_076007.HtM
BbS.okane403.info/PoSt/1121_509490.HtM
BbS.okane404.info/PoSt/1121_299916.HtM
BbS.okane405.info/PoSt/1121_343697.HtM
BbS.okane406.info/PoSt/1121_970474.HtM
BbS.okane407.info/PoSt/1121_070851.HtM
BbS.okane398.info/PoSt/1121_822687.HtM
BbS.okane399.info/PoSt/1121_106945.HtM
BbS.okane400.info/PoSt/1121_344446.HtM
BbS.okane401.info/PoSt/1121_149925.HtM
BbS.okane402.info/PoSt/1121_670554.HtM
BbS.okane403.info/PoSt/1121_594048.HtM
BbS.okane404.info/PoSt/1121_632520.HtM
BbS.okane405.info/PoSt/1121_933959.HtM
BbS.okane406.info/PoSt/1121_717340.HtM
BbS.okane407.info/PoSt/1121_504688.HtM
查看10道真题和解析