C++中的事件总线与观察者模式:实现与示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C++中的事件总线与观察者模式:从理论到实践



在现代C++软件开发中,组件的松耦合起着重要作用。观察者模式及其演进——事件总线——提供了一种优雅的机制,用于在对象之间组织交互,而无需创建硬性依赖。在本文中,我们将详细探讨如何在C++中实现这些模式,分析它们的优势和局限性,并提供实际的代码示例。



观察者模式:经典实现



观察者模式定义了对象之间的“一对多”关系:当一个对象(主题)改变其状态时,所有依赖于它的对象(观察者)都会自动收到通知。在C++中,经典实现如下所示:



#include <iostream>#include <vector>#include <memory>#include <algorithm>

// 观察者接口class IObserver {public: virtual ~IObserver() = default; virtual void update(const std::string& message) = 0;};

// 具体观察者class ConcreteObserver : public IObserver {private: std::string name;public: explicit ConcreteObserver(const std::string& n) : name(n) {} void update(const std::string& message) override { std::cout << "[" << name << "] 收到: " << message << std::endl; }};

// 主题(被观察对象)class Subject {private: std::vector<std::shared_ptr<IObserver>> observers; std::string state;public: void attach(std::shared_ptr<IObserver> observer) { observers.push_back(observer); } void detach(std::shared_ptr<IObserver> observer) { observers.erase( std::remove(observers.begin(), observers.end(), observer), observers.end() ); } void notify() { for (auto& observer : observers) { observer->update(state); } } void setState(const std::string& newState) { state = newState; notify(); }};

int main() { Subject subject; auto obs1 = std::make_shared<ConcreteObserver>("观察者 1"); auto obs2 = std::make_shared<ConcreteObserver>("观察者 2"); subject.attach(obs1); subject.attach(obs2); subject.setState("事件 #1 发生了!"); subject.detach(obs1); subject.setState("事件 #2 没有第一个观察者"); return 0;}


事件总线:集中式事件总线



事件总线扩展了观察者的思想,提供了一种集中式的消息交换机制。每个主题不再维护一个观察者列表,而是所有订阅和发布都通过一个统一的总线进行。这允许:

  • 降低耦合度——发送者和接收者彼此互不了解。
  • 简化扩展——新的事件类型可以在不修改现有代码的情况下添加。
  • 提供灵活性——可以在运行时添加和移除订阅者。


使用模板和std::function在C++中实现事件总线的示例:



#include <iostream>#include <unordered_map>#include <functional>#include <any>#include <typeindex>#include <vector>#include <memory>

// 事件基类struct Event { virtual ~Event() = default;};

// 具体事件struct UserLoginEvent : public Event { std::string username; explicit UserLoginEvent(std::string name) : username(std::move(name)) {}};

// 事件总线类class EventBus {private: std::unordered_map<std::type_index, std::vector<std::function<void(const std::any&)>>> hand

推荐