目标:能够实现在整个游戏中的消息传递。拥有方便的消息数据获取
使用单个数字作为一个消息的唯一ID,一个消息对应多个接受者.
消息接受者保存两个信息,一个是这个接受者的源,另一个是响应体。
所以 用来存储 消息对应的大致结构 就是 intID---<接受源,响应体>。
using
SenderTable=System.Collections.Generic.Dictionary<System.Object,System.Collections.Generic.List<System.EventHandler>>;
简化表的声明。
新建一个消息处理类
NotificationCenter.cs
{
将他做成单例的形式
定义结构对监听进行存储 private Dictionary<int , SenderTable> _table = new Dictionary<int , SenderTable>();#region 单例public readonly static NotificationCenter instance = new NotificationCenter();private NotificationCenter(){}#endregion
接下来提供 对这个字典的访问的接口:
private
SenderTable
GetSenderTable(int
notificationName)
然后要提供获取执行体列表的接口{if (!_table.ContainsKey(notificationName))_table.Add(notificationName , new SenderTable());return _table[notificationName];}
private List<EventHandler> GetObservers(SenderTable subTable , System.Object sender){if (!subTable.ContainsKey(sender))subTable.Add(sender , new List<EventHandler>());return subTable[sender];}
接下来提供 添加事件的的接口,主要的逻辑还是对这个字典数据的操作:
public void AddObserver(EventHandler handler , int notificationName){AddObserver(handler , notificationName , null);}public void AddObserver(EventHandler handler , int notificationName , System.Object sender){if (handler == null){Debug.LogError("Can't add a null event handler for notification, " + notificationName);return;}//if (string.IsNullOrEmpty(notificationName))//{// Debug.LogError("Can't observe an unnamed notification");// return;//}SenderTable subTable = GetSenderTable(notificationName);System.Object key = (sender != null) ? sender : this;List<EventHandler> list = GetObservers(subTable , key);if (!list.Contains(handler))list.Add(handler);}
有了注册,再就是对事件撤销的接口提供:
public void RemoveObserver(EventHandler handler){int[] keys = new int[_table.Keys.Count];_table.Keys.CopyTo(keys , 0);for (int i = keys.Length - 1 ; i >= 0 ; --i)RemoveObserver(handler , keys[i]);}public void RemoveObserver(EventHandler handler , int notificationName){if (handler == null){Debug.LogError("Can't remove a null event handler from notification");return;}//if (string.IsNullOrEmpty(notificationName))//{// Debug.LogError("A notification name is required to stop observation");// return;//}// No need to take action if we dont monitor this notificationif (!_table.ContainsKey(notificationName))return;System.Object[] keys = new object[_table[notificationName].Keys.Count];_table[notificationName].Keys.CopyTo(keys , 0);for (int i = keys.Length - 1 ; i >= 0 ; --i)RemoveObserver(handler , notificationName , keys[i]);}public void RemoveObserver(EventHandler handler , int notificationName , System.Object sender){//if (string.IsNullOrEmpty(notificationName))//{// Debug.LogError("A notification name is required to stop observation");// return;//}// No need to take action if we dont monitor this notificationif (!_table.ContainsKey(notificationName))return;SenderTable subTable = GetSenderTable(notificationName);System.Object key = (sender != null) ? sender : this;if (!subTable.ContainsKey(key))return;List<EventHandler> list = GetObservers(subTable , key);for (int i = list.Count - 1 ; i >= 0 ; --i){if (list[i] == handler){list.RemoveAt(i);break;}}if (list.Count == 0){subTable.Remove(key);if (subTable.Count == 0)_table.Remove(notificationName);}}
最后是对消息发送的接口:
为了减少各个类间的耦合性,可以将他进一步封装,这样在各个类里可以直接使用而不用实例化东西,既保持了代码的简洁性,对于查找引用也很方便,接口集中化,修改和移除时也很方便:public void PostNotification(int notificationName){PostNotification(notificationName , null);}public void PostNotification(int notificationName , System.Object sender){PostNotification(notificationName , sender , EventArgs.Empty);}public void PostNotification(int notificationName , System.Object sender , EventArgs e){//if (string.IsNullOrEmpty(notificationName))//{// Debug.LogError("A notification name is required to stop observation");// return;//}// No need to take action if we dont monitor this notificationif (!_table.ContainsKey(notificationName))return;// Post to subscribers who specified a sender to observeSenderTable subTable = GetSenderTable(notificationName);if (sender != null && subTable.ContainsKey(sender)){List<EventHandler> handlers = GetObservers(subTable , sender);for (int i = handlers.Count - 1 ; i >= 0 ; --i)handlers[i](sender , e);}// Post to subscribers who did not specify a sender to observeif (subTable.ContainsKey(this)){List<EventHandler> handlers = GetObservers(subTable , this);for (int i = handlers.Count - 1 ; i >= 0 ; --i)handlers[i](sender , e);}}
public static class ObjectExtensions{#region 事件 注册 、注销public static void PostNotification(this object obj , int notificationName){NotificationCenter.instance.PostNotification(notificationName , obj);}public static void PostNotification(this object obj , int notificationName , EventArgs e){NotificationCenter.instance.PostNotification(notificationName , obj , e);}public static void AddObserver(this object obj , EventHandler handler , int notificationName){NotificationCenter.instance.AddObserver(handler , notificationName);}public static void AddObserver(this object obj , EventHandler handler , int notificationName , object sender){NotificationCenter.instance.AddObserver(handler , notificationName , sender);}public static void RemoveObserver(this object obj , EventHandler handler){NotificationCenter.instance.RemoveObserver(handler);}public static void RemoveObserver(this object obj , EventHandler handler , int notificationName){NotificationCenter.instance.RemoveObserver(handler , notificationName);}public static void RemoveObserver(this object obj , EventHandler handler , int notificationName , System.Object sender){NotificationCenter.instance.RemoveObserver(handler , notificationName , sender);}#endregion#region 获取Unicode#endregion}public class EventArgsUs:EventArgs{public object param1;public object param2;public object param3;public EventArgsUs(object param1,object param2,object param3=null){this.param1 = param1;this.param2 = param2;this.param3 = param3;}}