|
| 1 | +# EventEmitter 使用指南 |
| 2 | + |
| 3 | +## 概述 |
| 4 | + |
| 5 | +`EventEmitter` 是一个基类,继承它即可为您的类提供完整的事件发射和监听功能。它基于观察者模式实现,支持类型安全的事件处理、同步和异步事件分发。 |
| 6 | + |
| 7 | +## 基本用法 |
| 8 | + |
| 9 | +### 1. 定义事件类 |
| 10 | + |
| 11 | +首先,您需要定义事件类。有几种方式: |
| 12 | + |
| 13 | +#### 方式一:手动定义(推荐) |
| 14 | +```cpp |
| 15 | +class MyEvent : public TypedEvent<MyEvent> { |
| 16 | +public: |
| 17 | + std::string message; |
| 18 | + int value; |
| 19 | + |
| 20 | + MyEvent(std::string msg, int val) |
| 21 | + : message(std::move(msg)), value(val) {} |
| 22 | +}; |
| 23 | +``` |
| 24 | +
|
| 25 | +#### 方式二:使用宏定义 |
| 26 | +```cpp |
| 27 | +DEFINE_EVENT_BEGIN(MyEvent) |
| 28 | + std::string message; |
| 29 | + int value; |
| 30 | + |
| 31 | + MyEvent(std::string msg, int val) |
| 32 | + : message(std::move(msg)), value(val) {} |
| 33 | +DEFINE_EVENT_END() |
| 34 | +``` |
| 35 | + |
| 36 | +#### 方式三:简单事件(仅数据成员) |
| 37 | +```cpp |
| 38 | +SIMPLE_EVENT(StatusEvent, |
| 39 | + bool success; |
| 40 | + std::string error_message; |
| 41 | +) |
| 42 | +``` |
| 43 | + |
| 44 | +### 2. 创建继承 EventEmitter 的类 |
| 45 | + |
| 46 | +```cpp |
| 47 | +class MyClass : public EventEmitter { |
| 48 | +public: |
| 49 | + void DoSomething() { |
| 50 | + // 触发同步事件 |
| 51 | + EmitSync<MyEvent>("Hello", 42); |
| 52 | + |
| 53 | + // 触发异步事件 |
| 54 | + EmitAsync<MyEvent>("Async Hello", 100); |
| 55 | + } |
| 56 | + |
| 57 | + void DoSomethingElse(const std::string& msg, int val) { |
| 58 | + // 直接传递参数构造事件 |
| 59 | + EmitSync<MyEvent>(msg, val); |
| 60 | + } |
| 61 | +}; |
| 62 | +``` |
| 63 | +
|
| 64 | +### 3. 添加事件监听器 |
| 65 | +
|
| 66 | +#### Lambda 函数监听器(推荐) |
| 67 | +```cpp |
| 68 | +MyClass obj; |
| 69 | +
|
| 70 | +size_t listener_id = obj.AddListener<MyEvent>([](const MyEvent& event) { |
| 71 | + std::cout << "收到事件: " << event.message << ", 值: " << event.value << std::endl; |
| 72 | +}); |
| 73 | +``` |
| 74 | + |
| 75 | +#### 类型化监听器 |
| 76 | +```cpp |
| 77 | +class MyListener : public TypedEventListener<MyEvent> { |
| 78 | +public: |
| 79 | + void OnTypedEvent(const MyEvent& event) override { |
| 80 | + std::cout << "监听器收到: " << event.message << std::endl; |
| 81 | + } |
| 82 | +}; |
| 83 | + |
| 84 | +MyListener listener; |
| 85 | +size_t id = obj.AddListener<MyEvent>(&listener); |
| 86 | +``` |
| 87 | +
|
| 88 | +### 4. 管理监听器 |
| 89 | +
|
| 90 | +```cpp |
| 91 | +// 移除特定监听器 |
| 92 | +obj.RemoveListener(listener_id); |
| 93 | +
|
| 94 | +// 移除某种事件类型的所有监听器 |
| 95 | +obj.RemoveAllListeners<MyEvent>(); |
| 96 | +
|
| 97 | +// 移除所有监听器 |
| 98 | +obj.RemoveAllListeners(); |
| 99 | +
|
| 100 | +// 检查监听器数量 |
| 101 | +size_t count = obj.GetListenerCount<MyEvent>(); |
| 102 | +size_t total = obj.GetTotalListenerCount(); |
| 103 | +
|
| 104 | +// 检查是否有监听器 |
| 105 | +bool has_listeners = obj.HasListeners<MyEvent>(); |
| 106 | +``` |
| 107 | + |
| 108 | +## API 参考 |
| 109 | + |
| 110 | +### EventEmitter 公共方法 |
| 111 | + |
| 112 | +#### 添加监听器 |
| 113 | +- `size_t AddListener<EventType>(TypedEventListener<EventType>* listener)` |
| 114 | + - 添加类型化监听器 |
| 115 | + - 返回监听器 ID |
| 116 | + |
| 117 | +- `size_t AddListener<EventType>(std::function<void(const EventType&)> callback)` |
| 118 | + - 添加 Lambda 函数监听器 |
| 119 | + - 返回监听器 ID |
| 120 | + |
| 121 | +#### 移除监听器 |
| 122 | +- `bool RemoveListener(size_t listener_id)` |
| 123 | + - 根据 ID 移除监听器 |
| 124 | + - 返回是否成功 |
| 125 | + |
| 126 | +- `void RemoveAllListeners<EventType>()` |
| 127 | + - 移除指定类型的所有监听器 |
| 128 | + |
| 129 | +- `void RemoveAllListeners()` |
| 130 | + - 移除所有监听器 |
| 131 | + |
| 132 | +#### 查询方法 |
| 133 | +- `size_t GetListenerCount<EventType>() const` |
| 134 | + - 获取指定事件类型的监听器数量 |
| 135 | + |
| 136 | +- `size_t GetTotalListenerCount() const` |
| 137 | + - 获取总监听器数量 |
| 138 | + |
| 139 | +- `bool HasListeners<EventType>() const` |
| 140 | + - 检查是否有指定类型的监听器 |
| 141 | + |
| 142 | +### EventEmitter 受保护方法(用于子类) |
| 143 | + |
| 144 | +#### 发射事件 |
| 145 | +- `void EmitSync(const Event& event)` |
| 146 | + - 同步发射事件对象 |
| 147 | + |
| 148 | +- `void EmitSync<EventType>(Args&&... args)` |
| 149 | + - 同步发射事件(完美转发参数) |
| 150 | + |
| 151 | +- `void EmitAsync(std::unique_ptr<Event> event)` |
| 152 | + - 异步发射事件对象 |
| 153 | + |
| 154 | +- `void EmitAsync<EventType>(Args&&... args)` |
| 155 | + - 异步发射事件(完美转发参数) |
| 156 | + |
| 157 | +## 完整示例 |
| 158 | + |
| 159 | +```cpp |
| 160 | +#include "event_emitter.h" |
| 161 | +#include <iostream> |
| 162 | + |
| 163 | +// 定义事件 |
| 164 | +class ButtonClickEvent : public TypedEvent<ButtonClickEvent> { |
| 165 | +public: |
| 166 | + std::string button_name; |
| 167 | + int x, y; |
| 168 | + |
| 169 | + ButtonClickEvent(std::string name, int x_pos, int y_pos) |
| 170 | + : button_name(std::move(name)), x(x_pos), y(y_pos) {} |
| 171 | +}; |
| 172 | + |
| 173 | +// 继承 EventEmitter 的类 |
| 174 | +class Button : public EventEmitter { |
| 175 | +public: |
| 176 | + Button(std::string name) : name_(std::move(name)) {} |
| 177 | + |
| 178 | + void Click(int x, int y) { |
| 179 | + std::cout << "按钮 '" << name_ << "' 被点击" << std::endl; |
| 180 | + EmitSync<ButtonClickEvent>(name_, x, y); |
| 181 | + } |
| 182 | + |
| 183 | +private: |
| 184 | + std::string name_; |
| 185 | +}; |
| 186 | + |
| 187 | +int main() { |
| 188 | + Button button("确定"); |
| 189 | + |
| 190 | + // 添加监听器 |
| 191 | + size_t id = button.AddListener<ButtonClickEvent>([](const ButtonClickEvent& event) { |
| 192 | + std::cout << "监听到点击: " << event.button_name |
| 193 | + << " 位置(" << event.x << ", " << event.y << ")" << std::endl; |
| 194 | + }); |
| 195 | + |
| 196 | + // 触发事件 |
| 197 | + button.Click(100, 200); |
| 198 | + |
| 199 | + // 清理 |
| 200 | + button.RemoveListener(id); |
| 201 | + |
| 202 | + return 0; |
| 203 | +} |
| 204 | +``` |
| 205 | +
|
| 206 | +## 最佳实践 |
| 207 | +
|
| 208 | +1. **使用 Lambda 函数监听器**:对于简单的事件处理逻辑,Lambda 函数更加简洁。 |
| 209 | +
|
| 210 | +2. **管理监听器生命周期**:确保在对象销毁前移除监听器,避免悬空指针。 |
| 211 | +
|
| 212 | +3. **异常处理**:EventEmitter 会捕获监听器中的异常,但不会传播。确保您的监听器代码健壮。 |
| 213 | +
|
| 214 | +4. **同步 vs 异步**: |
| 215 | + - 使用 `EmitSync` 进行即时处理 |
| 216 | + - 使用 `EmitAsync` 避免阻塞当前线程 |
| 217 | +
|
| 218 | +5. **事件设计**:保持事件类简单,只包含必要的数据。 |
| 219 | +
|
| 220 | +6. **性能考虑**:大量监听器可能影响性能,考虑按需添加/移除。 |
| 221 | +
|
| 222 | +## 线程安全 |
| 223 | +
|
| 224 | +EventEmitter 是线程安全的,可以在多线程环境中安全使用。异步事件会在后台线程中处理,而同步事件在当前线程中立即处理。 |
0 commit comments