using System; using UnityEngine; using System.Collections.Generic; namespace BallKingdomCrush { public abstract class BaseDispatcher : IDisposable where T : class, new() where Param : class { private static T m_instance; public static T Instance { get { if (m_instance == null) { m_instance = new T(); } return m_instance; } } private Dictionary>> m_msgPriorityDict = new(); private Dictionary>> m_msgDict = new(); private Dictionary>> m_msgFinallyDict = new(); private Dictionary>> m_msgOnceDict = new(); public void AddListener(Msg msgId, Action listener) { if (m_msgDict.TryGetValue(msgId, out var value)) { value.Add(listener); } else { var list = ListPool>.Get(); list.Add(listener); m_msgDict.Add(msgId, list); } } public void AddOnceListener(Msg msgId, Action listener) { if (m_msgOnceDict.TryGetValue(msgId, out var value)) { value.Add(listener); } else { var list = ListPool>.Get(); list.Add(listener); m_msgOnceDict.Add(msgId, list); } } public void RemoveListener(Msg msgId, Action listener) { if (m_msgDict.TryGetValue(msgId, out var list)) { if (list.Contains(listener)) { list.Remove(listener); if (list.Count == 0) { ListPool>.Release(list); m_msgDict.Remove(msgId); } } } } public void Dispatch(Msg msgId, Param param = null) { InvokeMethods(m_msgPriorityDict, msgId, param); InvokeMethods(m_msgDict, msgId, param); InvokeMethods(m_msgFinallyDict, msgId, param); InvokeMethods(m_msgOnceDict, msgId, param); if (m_msgOnceDict.ContainsKey(msgId)) { ListPool>.Release(m_msgOnceDict[msgId]); m_msgOnceDict.Remove(msgId); } } private void InvokeMethods(Dictionary>> msgDict, Msg msgId, Param param) { if (!msgDict.ContainsKey(msgId)) return; var rawList = msgDict[msgId]; int funcCount = rawList.Count; if (funcCount == 1) { Action onEvent = rawList[0]; onEvent(param); return; } var invokeFuncs = ListPool>.Get(); invokeFuncs.AddRange(rawList); for (var i = 0; i < funcCount; i++) { try { var onEvent = invokeFuncs[i]; onEvent(param); } catch (Exception e) { Debug.LogError(e); } } ListPool>.Release(invokeFuncs); } public void Dispose() { m_instance = null; m_msgPriorityDict.Clear(); m_msgDict.Clear(); m_msgFinallyDict.Clear(); m_msgOnceDict.Clear(); m_msgPriorityDict = null; m_msgDict = null; m_msgFinallyDict = null; m_msgOnceDict = null; } } }