初級知識六——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中的委托全部取出來,然后執行,又因為其實

      這里的每個委托在我們注冊的時候,就綁定了相應的處理方法,因此,此刻執行的委托,其實就是執行的我們綁定的具體的方法。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM