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

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

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

 public interface IEventCenter : IDestroy
{
bool AddEventListener(Enum EventType, EventHandler handler); bool RemoveEventListener(Enum EventType, EventHandler handler); //触发事件
void TriggerEvent(IEvent e); //广播事件
void BroadCastEvent(); }
 public delegate void EventHandler(IEvent evt);//顺带定义了下事件委托。

 public interface IEventHandlerManger : IEvent,IDestroy
{
bool AddHandler(EventHandler eventHandler); bool RemoveHandler(EventHandler eventHandler); void BroadCastEvent(IEvent evt); void Clear();
}

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

 {
private Dictionary<Enum, IEventHandlerManger> DictHandler = new Dictionary<Enum, IEventHandlerManger>(); private SafeQuene<IEvent> eventQuene = new SafeQuene<IEvent>(); public bool AddEventListener(Enum EventType, EventHandler handler)
{
bool isSuccessed;
       //如果不包含EventType,就将其加入到字典中,同时新建一个EventHandlerManager()
if (!DictHandler.ContainsKey(EventType))
{
DictHandler[EventType] = new EventHandlerManager();
}
        //然后将handler加入到新创建的EventHandlerManager中去。
isSuccessed = DictHandler[EventType].AddHandler(handler); return isSuccessed;
} public bool RemoveEventListener(Enum EventType, EventHandler handler)
{
if (DictHandler.ContainsKey(EventType))
{
DictHandler.Remove(EventType);
return true;
}
else
{
return false;
}
} public void TriggerEvent(IEvent e)
{
this.eventQuene.EnQuene(e);
} #region 广播事件相关 public void Update()
{
BroadCastEvent();
}
public void BroadCastEvent()
{
if (eventQuene.Count<)
{
return;
} IEvent e = eventQuene.DeQuene(); BroadCastEvent(e);
} public void BroadCastEvent(IEvent e)
{
if (e == null)
{
return;
} Enum type = e.EventType; if (!DictHandler.ContainsKey(type))
{
e.DestroySelf();
} DictHandler[type].BroadCastEvent(e);
e.DestroySelf(); } #endregion #region 清除数据相关 public void DestroySelf()
{
ClearEvenQueneAndDictHandler();
} public void OnDestroy()
{
ClearEvenQueneAndDictHandler();
} public void ClearEventQuene()
{
eventQuene.Clear();
} public void ClearEvenQueneAndDictHandler()
{
DictHandler.Clear();
ClearEventQuene();
} #endregion
}
 public class EventHandlerManager : IEventHandlerManger
{
private Enum _EventType; private List<EventHandler> handler = new List<EventHandler>(); public Enum EventType
{
get
{
return _EventType;
}
} public bool AddHandler(EventHandler eventHandler)
{
if (handler.Contains(eventHandler))
{
return false;
} handler.Add(eventHandler);
return true;
} public bool RemoveHandler(EventHandler eventHandler)
{
if (!handler.Contains(eventHandler))
{
return false;
} handler.Remove(eventHandler);
return true;
} public void BroadCastEvent(IEvent evt)
{
List<EventHandler> list = new List<EventHandler>();
list.AddRange(handler); foreach (EventHandler item in list)
{
item(evt);
}
} public void Clear()
{
handler.Clear();
} public void DestroySelf()
{
if (handler !=null)
{
Clear();
handler = null;
}
} }

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

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

public enum FBIEvent
{
TheyHaveGuns = ,
TheyUseBoom =,
TheyAreCute =,
}

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

 public class FBI
{
void HavaGun(IEvent e)
{
Debug.Log("yellow gun!");
} void UseBoom(IEvent e)
{
Debug.Log("yellow gun!");
} void TheyCute(IEvent e)
{
Debug.Log("Impossible");
}
}

最后,只需要调用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中的委托全部取出来,然后执行,又因为其实

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

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

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

    Caddy源码阅读(二)启动流程与 Event 事件通知 Preface Caddy 是 Go 语言构建的轻量配置化服务器.https://github.com/caddyserver/caddy C ...

  2. SQL Server 事件通知(Event notifications)

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 基础知识(Rudimentary Knowledge) 事件通知监控DDL(NotifyQue ...

  3. PHP 命令行模式实战之cli+mysql 模拟队列批量发送邮件(在Linux环境下PHP 异步执行脚本发送事件通知消息实际案例)

    源码地址:https://github.com/Tinywan/PHP_Experience 测试环境配置: 环境:Windows 7系统 .PHP7.0.Apache服务器 PHP框架:ThinkP ...

  4. 很幽默的讲解六种Socket IO模型 Delphi版本(自己Select查看,WM_SOCKET消息通知,WSAEventSelect自动收取,Overlapped I/O 事件通知模型,Overlapped I/O 完成例程模型,IOCP模型机器人)

    很幽默的讲解六种Socket IO模型(转)本文简单介绍了当前Windows支持的各种Socket I/O模型,如果你发现其中存在什么错误请务必赐教. 一:select模型 二:WSAAsyncSel ...

  5. ABP文档 - 通知系统

    文档目录 本节内容: 简介 发送模式 通知类型 通知数据 通知重要性 关于通知持久化 订阅通知 发布通知 用户通知管理器 实时通知 客户端 通知存储 通知定义 简介 通知用来告知用户系统里特定的事件发 ...

  6. ABP理论学习之通知系统

    返回总目录 本篇目录 介绍 订阅通知 发布通知 用户通知管理者 实时通知 通知存储 通知定义 介绍 通知(Notification)用于告知用户系统中的特定事件.ABP提供了基于实时通知基础设施的发布 ...

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

    转载: http://blog.csdn.net/wuhzossibility/article/details/8079025 http://blog.chinaunix.net/uid-277176 ...

  8. 重叠I/O之事件通知

      在 Winsock 中,重叠 I/O(Overlapped I/O)模型能达到更佳的系统性能,高于select模型.异步选择和事件选择三种.重叠模型的基本设计原理便是让应用程序使 用一个重叠的数据 ...

  9. iOS 原生模块 给 Javascript(ReactNative) 发送事件 (通知监听)

    官方中文文档是这样描述的:   就给我们这几句话 就打发我们了. 按照上面的写法,根本不知道  - (void)calendarEventReminderReceived:(NSNotificatio ...

随机推荐

  1. OAuth2.0-3客户端授权放到数据库

    授权得客户端信息.授权码信息全都存在数据库 1.建表 官方给了个sql文件:https://github.com/spring-projects/spring-security-oauth/blob/ ...

  2. nvidia-smi:控制您的GPU

    翻译  https://www.microway.com/hpc-tech-tips/nvidia-smi_control-your-gpus/ 大多数用户知道如何检查其CPU的状态,查看多少系统内存 ...

  3. IDEA必备插件系列-Rainbow Brackets(彩虹括号)

    Rainbow Brackets ,就是彩虹括号,各种鲜明颜色的括号 这个一个开源的项目: https://github.com/izhangzhihao/intellij-rainbow-brack ...

  4. 会话机制,Cookie和Session详解

    转载自:https://www.cnblogs.com/whgk/p/6422391.html 很大一部分应该知道什么是会话机制,也能说的出几句,我也大概了解一点,但是学了之后几天不用,立马忘的一干二 ...

  5. 安装Scrapy的时候报错error: Microsoft Visual C++ 14.0 is required.

    error: Microsoft Visual C++ 14.0 is required. 问题:我在python安装Scrapy的时候发现报错,并安装不上. 解决思路:安装这个微软的库,但是这个库很 ...

  6. Javascript注意点

    Javascript注意点 在img标签中的src如果为相对路径, 但是在js获取的时候会转为全路径 候选框中, 在执行onclick之前, 会由于html的特征先设置checked属性 为a标签添加 ...

  7. NodeJs path.resolve的使用

    __dirname __dirname 指向运行代码的文件夹 console.info('__dirname', __dirname) // C:\Leslie\Web_learning\Daily- ...

  8. LeetCode 413 Arithmetic Slices详解

    这个开始自己做的动态规划复杂度达到了O(n), 是用的是2维的矩阵来存前面的数据,复杂度太高了, 虽然好理解,但是没效率,后面看这个博客发现没有动态规划做了这个题 也是比较厉害. 转载地址: http ...

  9. bluecms v1.6 代码审计

    0x01 使用seay源代码审计系统进行审计 扫描到了很多个可疑漏洞,不过工具都有一定的误报,下面我们就逐个进行验证 0x02 /ad_js.php SQL注入漏洞 查看源码,我们发现程序通过GET方 ...

  10. js获取当前地址信息

    var url = window.location.href; //获取当前窗口的Url; 结果:http://localhost:61768/Home/Index?id=2&age=18 v ...