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::liststd::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

#牛客AI配图神器#

全部评论

相关推荐

点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务