zoukankan      html  css  js  c++  java
  • 初级知识六——C#事件通知系统实现(观察者模式运用)

    观察者模式,绝对是游戏中十分重要的一种模式,运用这种模式,可以让游戏模块间的通信变得简单,耦合度也会大大降低,下面讲解如何利用C#实现事件通知系统。

    补充,首先说下这个系统的实现原理,不然一头扎进去就难受了,这个系统的关键就在于两个类,EventCenter 和Handler,她们关系如下:

    首先定义两个接口,IEventCenter 和IEventHandlerManager,代码如下:

     1 public interface IEventCenter : IDestroy
     2 {
     3     bool AddEventListener(Enum EventType, EventHandler handler);
     4 
     5     bool RemoveEventListener(Enum EventType, EventHandler handler);
     6 
     7     //触发事件
     8     void TriggerEvent(IEvent e);
     9 
    10     //广播事件
    11     void BroadCastEvent();
    12 
    13 }
     1 public delegate void EventHandler(IEvent evt);//顺带定义了下事件委托。
     2 
     3 public interface IEventHandlerManger : IEvent,IDestroy
     4 {
     5     bool AddHandler(EventHandler eventHandler);
     6 
     7     bool RemoveHandler(EventHandler eventHandler);
     8 
     9     void BroadCastEvent(IEvent evt);
    10 
    11     void Clear();
    12 }

    定义完两个接口后,就分别开始实现两个接口,两个接口的实现分别为EventCenter 和EventHandlerManager,代码如下  1 public class EventCenter : MonoSingleton<EventCenter>, IEventCenter

      2 {
      3     private Dictionary<Enum, IEventHandlerManger> DictHandler = new Dictionary<Enum, IEventHandlerManger>();
      4 
      5     private SafeQuene<IEvent> eventQuene = new SafeQuene<IEvent>();
      6 
      7 
      8     public bool AddEventListener(Enum EventType, EventHandler handler)
      9     {
     10         bool isSuccessed;
           //如果不包含EventType,就将其加入到字典中,同时新建一个EventHandlerManager()
    11 if (!DictHandler.ContainsKey(EventType)) 12 { 13 DictHandler[EventType] = new EventHandlerManager(); 14 }
            //然后将handler加入到新创建的EventHandlerManager中去。
    15 isSuccessed = DictHandler[EventType].AddHandler(handler); 16 17 return isSuccessed; 18 } 19 20 public bool RemoveEventListener(Enum EventType, EventHandler handler) 21 { 22 if (DictHandler.ContainsKey(EventType)) 23 { 24 DictHandler.Remove(EventType); 25 return true; 26 } 27 else 28 { 29 return false; 30 } 31 } 32 33 public void TriggerEvent(IEvent e) 34 { 35 this.eventQuene.EnQuene(e); 36 } 37 38 39 #region 广播事件相关 40 41 42 public void Update() 43 { 44 BroadCastEvent(); 45 } 46 public void BroadCastEvent() 47 { 48 if (eventQuene.Count<1) 49 { 50 return; 51 } 52 53 IEvent e = eventQuene.DeQuene(); 54 55 BroadCastEvent(e); 56 } 57 58 public void BroadCastEvent(IEvent e) 59 { 60 if (e == null) 61 { 62 return; 63 } 64 65 Enum type = e.EventType; 66 67 if (!DictHandler.ContainsKey(type)) 68 { 69 e.DestroySelf(); 70 } 71 72 DictHandler[type].BroadCastEvent(e); 73 e.DestroySelf(); 74 75 } 76 77 #endregion 78 79 #region 清除数据相关 80 81 82 public void DestroySelf() 83 { 84 ClearEvenQueneAndDictHandler(); 85 } 86 87 public void OnDestroy() 88 { 89 ClearEvenQueneAndDictHandler(); 90 } 91 92 public void ClearEventQuene() 93 { 94 eventQuene.Clear(); 95 } 96 97 public void ClearEvenQueneAndDictHandler() 98 { 99 DictHandler.Clear(); 100 ClearEventQuene(); 101 } 102 103 #endregion 104 }
     1 public class EventHandlerManager : IEventHandlerManger
     2 {
     3     private Enum _EventType;
     4 
     5     private List<EventHandler> handler = new List<EventHandler>();
     6 
     7     public Enum EventType
     8     {
     9         get
    10         {
    11             return _EventType;
    12         }
    13     }
    14 
    15     public bool AddHandler(EventHandler eventHandler)
    16     {
    17         if (handler.Contains(eventHandler))
    18         {
    19             return false;
    20         }
    21 
    22         handler.Add(eventHandler);
    23         return true;
    24     }
    25 
    26     public bool RemoveHandler(EventHandler eventHandler)
    27     {
    28         if (!handler.Contains(eventHandler))
    29         {
    30             return false;
    31         }
    32 
    33         handler.Remove(eventHandler);
    34         return true;
    35     }
    36 
    37     public void BroadCastEvent(IEvent evt)
    38     {
    39         List<EventHandler> list = new List<EventHandler>();
    40         list.AddRange(handler);
    41 
    42         foreach (EventHandler item in list)
    43         {
    44             item(evt);
    45         }
    46     }
    47 
    48 
    49     public void Clear()
    50     {
    51         handler.Clear();
    52     }
    53 
    54     public void DestroySelf()
    55     {
    56         if (handler !=null)
    57         {
    58             Clear();
    59             handler = null;
    60         }
    61     }
    62 
    63    
    64 }

    ok,补充说明一下,IEvent接口很简单,里面定义了一个Enum EventType的Get方法,IDestroy接口则定义了一个DestroySelf()的方法。safeQuene<T>是一个线程安全的Quene<T>,其余和Quene<T>一样。

    运用这套事件广播系统也十分简单,首先,在需要有事件通知的地方预定一个enum类型,比如:

    public enum FBIEvent
    {
         TheyHaveGuns = 1,
         TheyUseBoom =2,
         TheyAreCute =3,           
    }

    然后需要定义这三个枚举类型对应的操作函数,例如:

     1 public class FBI
     2 {
     3     void HavaGun(IEvent e)
     4     {
     5         Debug.Log("yellow gun!");
     6     }
     7 
     8     void UseBoom(IEvent e)
     9     {
    10           Debug.Log("yellow gun!");
    11     }
    12 
    13     void TheyCute(IEvent e)
    14     {
    15          Debug.Log("Impossible");
    16     }
    17 }

    最后,只需要调用EventCenter的AddEventListener()方法,将其注册进入EventCenter的DicrtHandler 字典中,就大功告成了。

      触发流程:

        1 其他方法,触发EventCenter的TriggerEvent(IEvent e)方法。

        2 EventCenter 的eventQuene会增加一个实现了IEvent接口的类。

        3 在Update()中不停执行的BroadCastEvent()函数,会从eventQuene中取出类,然后执行BroadCastEvent(IEvent e)方法。

        4 根据传入的EventType类型,将从DirctHandler中取出对应的IEventHandlerManager对象,然后执行其BroadCastEvent(EventHandler hanlder)方法,

         这里根据多态,实际上执行的是EventHandleManager类的BroadCastEvent(EventHandler hanlder)方法。

        5 因为EventHandleManager的BroadCastEvent(EventHandler hanlder)类其实就是将该类中的List Handler中的委托全部取出来,然后执行,又因为其实

          这里的每个委托在我们注册的时候,就绑定了相应的处理方法,因此,此刻执行的委托,其实就是执行的我们绑定的具体的方法。

  • 相关阅读:
    互斥锁Mutex与信号量Semaphore的区别
    c/c++强制类型转换
    c++中的隐藏、重载、覆盖(重写)
    运算符重载详解
    类的大小
    C++ static、const和static const 以及它们的初始化
    一种隐蔽性较高的Java ConcurrentModificationException异常场景
    Java编码常见的Log日志打印问题
    Java编程常见缺陷汇总(一)
    Java字符串连接的多种实现方法及效率对比
  • 原文地址:https://www.cnblogs.com/leiGameDesigner/p/7119155.html
Copyright © 2011-2022 走看看