什么是事件总线,它是发布-订阅模式的一种实现。最近从事的工作中,就用到一种事件总线机制。
事件发送者将事件发布到一个总线上(抛出事件),订阅者通过在总线上注册(监听总线),达到订阅总线事件的目的。这种模型允许不同的组件或者模块之间以较低的耦合进行通信。
C++实现的简化版如下:
- template <typename EventClass>
- class EventBus {
- public:
- EventBus() = default;
- ~EventBus() = default;
-
- static void Register(std::weak_ptr<EventClass> event) {
- for (auto& ev : events_) {
- auto ev_ptr = ev.lock();
- auto event_ptr = event.lock();
- if (ev_ptr == event_ptr) {
- INFO("skip exist event!");
- return;
- }
- }
- events_.emplace_back(event);
- }
-
- static void Unregister(std::weak_ptr<EventClass> event) {
- for (auto ev_it = events_.begin(); ev_it != events_.end(); ++ev_it) {
- auto ev_ptr = ev_it->lock();
- auto event_ptr = event.lock();
- if (ev_ptr == event_ptr) {
- events_.erase(ev_it);
- return;
- }
- }
- }
-
- template<typename EventFun, typename... EventArgs>
- static void OnEvent(EventFun fun, EventArgs&&... args) {
- for (const auto& ev : events_) {
- auto ptr = ev.lock();
- if (!ptr) {
- ERROR("skip not exist event!");
- continue;
- }
-
- auto obj = ptr.get();
- (obj->*fun)(args...);
- }
- }
-
- private:
- static std::list<std::weak_ptr<EventClass>> events_;
- };
-
- template <typename EventClass>
- std::list<std::weak_ptr<EventClass>> EventBus<EventClass>::events_;
其中Register与Unregister接口供监听者向总线上注册监听,OnEvent接口供事件发送者抛出事件,测试demo如下:
- class Base {
- public:
- virtual void print(int a) = 0;
- };
-
- class Test_One : public std::enable_shared_from_this<Test_One>,
- public Base {
- public:
- virtual void print(int a) override {
- printf("This Is Test Print: %d !\n", a);
- }
- };
-
- class Test_Two : public std::enable_shared_from_this<Test_Two>,
- public Base {
- public:
- virtual void print(int a) override {
- printf("This Is Test2 Print: %d !\n", a);
- }
- };
-
-
- int main(int argc, char *argv[])
- {
- auto ptr1 = std::make_shared<Test_One>();
- auto weak_ptr1 = std::weak_ptr<Base>(ptr1);
- auto ptr2 = std::make_shared<Test_Two>();
- auto weak_ptr2 = std::weak_ptr<Base>(ptr2);
-
- EventBus<Base>::Register(weak_ptr1);
- EventBus<Base>::Register(weak_ptr2);
-
- EventBus<Base>::OnEvent(&Base::print, 123);
-
- INFO("unregister ptr1");
- EventBus<Base>::Unregister(weak_ptr1);
- EventBus<Base>::OnEvent(&Base::print, 123);
-
- INFO("unregister ptr2");
- EventBus<Base>::Unregister(weak_ptr2);
- EventBus<Base>::OnEvent(&Base::print, 123);
-
- return 0;
- }
运行结果:
可以看到在总线上注册的模块,当事件发生时,能够执行该事件对应的动作,这就是简单的总线模型。
附:
源码:GitHub - Fireplusplus/event_bus: simple event bus for c++