初级知识六——C#事件通知系统实现(观察者模式运用)

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

首先定义两个接口,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中的委托全部取出来,然后执行,又因为其实

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

时间: 2024-12-26 23:17:28

初级知识六——C#事件通知系统实现(观察者模式运用)的相关文章

Caddy源码阅读(二)启动流程与 Event 事件通知

Caddy源码阅读(二)启动流程与 Event 事件通知 Preface Caddy 是 Go 语言构建的轻量配置化服务器.https://github.com/caddyserver/caddy Caddy 整个软件可以说是由不同的 插件 堆砌起来的.自己本身仅提供 Plugin 的注册运行逻辑和 Server 的监听服务功能. 学习 caddy 的源码,实际上是学习 如何构建一个 松耦合的 抽象 Plugin 设计,即模块化插拔的做法. 所以我们的源码阅读,围绕 Caddy 为 Plugin

Linux内核基础--事件通知链(notifier chain)

转载: http://blog.csdn.net/wuhzossibility/article/details/8079025 http://blog.chinaunix.net/uid-27717694-id-4286337.html 内核通知链 1.1. 概述 Linux内核中各个子系统相互依赖,当其中某个子系统状态发生改变时,就必须使用一定的机制告知使用其服务的其他子系统,以便其他子系统采取相应的措施.为满足这样的需求,内核实现了事件通知链机制(notificationchain). 通知

&lt;&lt;ABP文档&gt;&gt; 通知系统

文档目录 本节内容: 简介 发送模式 通知类型 通知数据 通知重要性 关于通知持久化 订阅通知 发布通知 用户通知管理器 实时通知 客户端 通知存储 通知定义 简介 通知用来告知用户系统里特定的事件发生了,ABP提供一个发布/订阅,它基于实时通知基础框架. 发送模式 有两种方式可以发送通知给用户: 用户订阅一个特定的通知类型,然后我们发布一个此类型的通知,它会分发给所有订阅的用户,这就是发布/订阅模式. 我们可以直接发送一个通知给目标用户(users). 通知类型 有两种通知类型: 一般通知:任

网络编程(三):从libevent到事件通知机制

由于POSIX标准的滞后性事件通知API的混乱一直保持到现在 所有就有libevent.libev甚至后面的libuv的出现为跨平台编程扫清障碍. 下面是WikiPedia对于libevent的介绍    libevent是一个异步事件处理软件函式库以BSD许可证发布. libevent提供了一组应用程序编程接口API让程序员     可以设定某些事件发生时所执行的函式也就是说libevent可以用来取代网络服务器所使用的事件循环检查框架. 由于可以省去对网络的处理且拥有不错的效能 有些软件使用

Linux内核基础--事件通知链(notifier chain)【转】

转自:http://blog.csdn.net/wuhzossibility/article/details/8079025 内核通知链 1.1. 概述 Linux内核中各个子系统相互依赖,当其中某个子系统状态发生改变时,就必须使用一定的机制告知使用其服务的其他子系统,以便其他子系统采取相应的措施.为满足这样的需求,内核实现了事件通知链机制(notificationchain). 通知链只能用在各个子系统之间,而不能在内核和用户空间进行事件的通知.组成内核的核心系统代码均位于kernel目录下,

iOS日历相关操作--读取系统日历、添加事件到系统日历

1 读取系统日历 let eventStore = EKEventStore() let tempFormatter = NSDateFormatter() tempFormatter.dateFormat = "dd.MM.yyyy HH:mm" //获取一个时间段中的日历事件 let startDate = tempFormatter.dateFromString("10.08.2016 15:10")! let endDate = tempFormatter.

重叠I/O之事件通知

在 Winsock 中,重叠 I/O(Overlapped I/O)模型能达到更佳的系统性能,高于select模型.异步选择和事件选择三种.重叠模型的基本设计原理便是让应用程序使 用一个重叠的数据结构(WSAOVERLAPPED),一次投递一个或多个 Winsock I/O 请求.针对这些提交的请求,在它们完成之后,我们的应用程序会收到通知,于是 我们就可以对数据进行处理了. 要想在一个套接字上使用重叠 I/O 模型,首先必须使用 WSA_FLAG_OVERLAPPED 这个标志,创建一个套接字

ASP.NET Core 2.2 基础知识(六) 配置(内含MySql+EF)

原文:ASP.NET Core 2.2 基础知识(六) 配置(内含MySql+EF) 先上一段代码,了解一下 .NET Core 配置数据的结构. 新建一个 控制台项目,添加一个文件 json.json ,文件内容如下: { "country": "cn", "person": { "id": 1, "address": { "addName": "chengdu"

重大事件通知!微服售后服务系统升级……

重大事件通知!!! 为了节省微服各位上帝客户们宝贵的时间 提高服务体验,减少沟通成本 微服售后服务系统升级啦 来来来! 给我2分钟为客户宝宝们简单介绍下 相信各位微服的上帝们都遇到过系统出现bug 或者操作不当引起故障的时候 只能在微信群里@售后同学 有可能这位售后同学正在打盹中 一打盹20分钟就过去了 受理后也不清楚进展到什么阶段了. 现在不用担心了, 有了微信提交工单系统, 不管售后同学在打盹.上厕所.吃饭... 一切都不是问题! 一切都不是问题! 一切都不是问题! 交给我们的自助"工单系统