文档目录

一、传统观察者 vs 现代写法

传统:

struct Observer {
    virtual void onEvent(const Event&) = 0;
};

class Subject {
    std::vector<Observer*> observers_;
public:
    void attach(Observer* o) { observers_.push_back(o); }
    void notify(const Event& e) {
        for (auto* o : observers_) o->onEvent(e);
    }
};

问题:Observer 必须继承虚基类,生命周期由 Subject 外部管理(悬垂指针风险)。

现代写法:

class EventBus {
    std::vector<std::function<void(const Event&)>> handlers_;

public:
    // 接受 lambda、函数指针、任何可调用对象
    template <typename F>
    void subscribe(F&& handler) {
        handlers_.push_back(std::forward<F>(handler));
    }

    void fire(const Event& event) {
        for (auto& h : handlers_) {
            h(event);
        }
    }
};

// 使用——不需要继承任何东西
EventBus bus;
bus.subscribe([](const Event& e) {
    std::cout << "received: " << e.type << "\n";
});

Server server;
server.on_connect([&bus](ConnectionPtr conn) {
    bus.fire(Event{"connected"});
});

二、生命周期管理

现代观察者模式的最大问题:订阅者的生命周期。如果订阅者先于 EventBus 销毁,但订阅 lambda 捕获了订阅者的 this 指针,EventBus 触发事件时就是 Use-After-Free。

解决方案:用 shared_ptr + weak_ptr:

class Subscriber : public std::enable_shared_from_this<Subscriber> {
public:
    void subscribe(EventBus& bus) {
        auto weak_self = weak_from_this();  // C++17
        bus.subscribe([weak_self](const Event& e) {
            if (auto self = weak_self.lock()) {
                self->handleEvent(e);  // Subscriber 还活着,安全处理
            }
            // 如果 Subscriber 已销毁,什么都不做
        });
    }

    void handleEvent(const Event& e) { /* ... */ }
};