Unity 事件管理器(EventManager) 与 事件分发器(EventDispatcher) 的差异对比

数据结构与单例模式‌

  • 事件管理器‌
    使用字典集中管理事件类型与回调的映射关系,并采用单例模式确保全局唯一性:
public class EventManager {
    
    
    private static EventManager _instance;
    private Dictionary<string, Action<object>> _eventDict = new Dictionary<string, Action<object>>();

    public static EventManager Instance {
    
    
        get {
    
    
            if (_instance == null) _instance = new EventManager();
            return _instance;
        }
    }

    // 订阅/触发/取消方法见下文
}

‌特点‌:集中式存储,通过单例全局访问‌。

  • 事件分发器‌
    可能采用更轻量的结构(如委托链),部分实现会省略单例,允许独立实例化:
public class EventDispatcher {
    
    
    private Dictionary<EventType, Action<object>> _listeners = new Dictionary<EventType, Action<object>>();

    // 直接通过实例调用方法(非单例)
    public void Dispatch(EventType type, object data) {
    
    
        if (_listeners.TryGetValue(type, out Action<object> handler)) {
    
    
            handler?.Invoke(data);
        }
    }
}

‌特点‌:灵活性更高,可针对不同模块创建独立分发器‌。

订阅与触发方法‌

  • 事件管理器‌
    提供标准化的订阅和触发接口,强调生命周期管理:
// 订阅事件
public void AddListener(string eventName, Action<object> callback) {
    
    
    if (_eventDict.ContainsKey(eventName)) {
    
    
        _eventDict[eventName] += callback;
    } else {
    
    
        _eventDict[eventName] = callback;
    }
}

// 触发事件
public void TriggerEvent(string eventName, object data = null) {
    
    
    if (_eventDict.TryGetValue(eventName, out Action<object> handler)) {
    
    
        handler?.Invoke(data);
    }
}

‌设计目标‌:统一管理事件,避免内存泄漏(需手动取消订阅)‌。

  • 事件分发器‌
    更注重分发效率和参数类型安全,可能引入泛型:
public void AddListener<T>(EventType type, Action<T> callback) {
    
    
    if (!_listeners.ContainsKey(type)) {
    
    
        _listeners[type] = (data) => callback((T)data);
    } else {
    
    
        _listeners[type] += (data) => callback((T)data);
    }
}

public void Dispatch<T>(EventType type, T data) {
    
    
    if (_listeners.TryGetValue(type, out Action<object> handler)) {
    
    
        handler?.Invoke(data);
    }
}

‌设计目标‌:减少类型转换,支持强类型参数传递‌。

取消订阅逻辑‌

  • 事件管理器‌
    需显式调用取消订阅方法,并清理空事件:
public void RemoveListener(string eventName, Action<object> callback) {
    
    
    if (_eventDict.ContainsKey(eventName)) {
    
    
        _eventDict[eventName] -= callback;
        if (_eventDict[eventName] == null) {
    
    
            _eventDict.Remove(eventName);
        }
    }
}

‌关键点‌:强制生命周期管理,防止无效回调残留‌。

  • 事件分发器‌
    可能简化取消逻辑(依赖委托链自动管理):
public void RemoveListener(EventType type, Action<object> callback) {
    
    
    if (_listeners.ContainsKey(type)) {
    
    
        _listeners[type] -= callback;
    }
}

‌关键点‌:依赖委托链的自动清理机制,适用于高频事件‌。

总结对比表‌

‌功能‌ 事件管理器‌ ‌事件分发器‌
存储结构 字典(键为字符串或枚举)‌ 字典或委托链(键常为枚举)‌
单例模式 强制全局单例‌ 可选单例或独立实例‌
参数传递 弱类型(object)‌ 泛型强类型(如 EventData)‌
适用场景 全局低频事件(如成就、UI状态)‌ 模块高频事件(如战斗、输入)‌

代码差异核心‌

  • 事件管理器通过单例和字典实现‌集中控制‌,适合全局跨模块通信‌。
  • 事件分发器通过泛型和轻量结构优化‌分发效率‌,适合高频局部事件‌。