初级知识六——C#事件通知系统实现(观察者模式运用)
观察者模式,绝对是游戏中十分重要的一种模式,运用这种模式,可以让游戏模块间的通信变得简单,耦合度也会大大降低,下面讲解如何利用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#事件通知系统实现(观察者模式运用)的更多相关文章
- Caddy源码阅读(二)启动流程与 Event 事件通知
Caddy源码阅读(二)启动流程与 Event 事件通知 Preface Caddy 是 Go 语言构建的轻量配置化服务器.https://github.com/caddyserver/caddy C ...
- SQL Server 事件通知(Event notifications)
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 基础知识(Rudimentary Knowledge) 事件通知监控DDL(NotifyQue ...
- PHP 命令行模式实战之cli+mysql 模拟队列批量发送邮件(在Linux环境下PHP 异步执行脚本发送事件通知消息实际案例)
源码地址:https://github.com/Tinywan/PHP_Experience 测试环境配置: 环境:Windows 7系统 .PHP7.0.Apache服务器 PHP框架:ThinkP ...
- 很幽默的讲解六种Socket IO模型 Delphi版本(自己Select查看,WM_SOCKET消息通知,WSAEventSelect自动收取,Overlapped I/O 事件通知模型,Overlapped I/O 完成例程模型,IOCP模型机器人)
很幽默的讲解六种Socket IO模型(转)本文简单介绍了当前Windows支持的各种Socket I/O模型,如果你发现其中存在什么错误请务必赐教. 一:select模型 二:WSAAsyncSel ...
- ABP文档 - 通知系统
文档目录 本节内容: 简介 发送模式 通知类型 通知数据 通知重要性 关于通知持久化 订阅通知 发布通知 用户通知管理器 实时通知 客户端 通知存储 通知定义 简介 通知用来告知用户系统里特定的事件发 ...
- ABP理论学习之通知系统
返回总目录 本篇目录 介绍 订阅通知 发布通知 用户通知管理者 实时通知 通知存储 通知定义 介绍 通知(Notification)用于告知用户系统中的特定事件.ABP提供了基于实时通知基础设施的发布 ...
- Linux内核基础--事件通知链(notifier chain)
转载: http://blog.csdn.net/wuhzossibility/article/details/8079025 http://blog.chinaunix.net/uid-277176 ...
- 重叠I/O之事件通知
在 Winsock 中,重叠 I/O(Overlapped I/O)模型能达到更佳的系统性能,高于select模型.异步选择和事件选择三种.重叠模型的基本设计原理便是让应用程序使 用一个重叠的数据 ...
- iOS 原生模块 给 Javascript(ReactNative) 发送事件 (通知监听)
官方中文文档是这样描述的: 就给我们这几句话 就打发我们了. 按照上面的写法,根本不知道 - (void)calendarEventReminderReceived:(NSNotificatio ...
随机推荐
- OAuth2.0-3客户端授权放到数据库
授权得客户端信息.授权码信息全都存在数据库 1.建表 官方给了个sql文件:https://github.com/spring-projects/spring-security-oauth/blob/ ...
- nvidia-smi:控制您的GPU
翻译 https://www.microway.com/hpc-tech-tips/nvidia-smi_control-your-gpus/ 大多数用户知道如何检查其CPU的状态,查看多少系统内存 ...
- IDEA必备插件系列-Rainbow Brackets(彩虹括号)
Rainbow Brackets ,就是彩虹括号,各种鲜明颜色的括号 这个一个开源的项目: https://github.com/izhangzhihao/intellij-rainbow-brack ...
- 会话机制,Cookie和Session详解
转载自:https://www.cnblogs.com/whgk/p/6422391.html 很大一部分应该知道什么是会话机制,也能说的出几句,我也大概了解一点,但是学了之后几天不用,立马忘的一干二 ...
- 安装Scrapy的时候报错error: Microsoft Visual C++ 14.0 is required.
error: Microsoft Visual C++ 14.0 is required. 问题:我在python安装Scrapy的时候发现报错,并安装不上. 解决思路:安装这个微软的库,但是这个库很 ...
- Javascript注意点
Javascript注意点 在img标签中的src如果为相对路径, 但是在js获取的时候会转为全路径 候选框中, 在执行onclick之前, 会由于html的特征先设置checked属性 为a标签添加 ...
- NodeJs path.resolve的使用
__dirname __dirname 指向运行代码的文件夹 console.info('__dirname', __dirname) // C:\Leslie\Web_learning\Daily- ...
- LeetCode 413 Arithmetic Slices详解
这个开始自己做的动态规划复杂度达到了O(n), 是用的是2维的矩阵来存前面的数据,复杂度太高了, 虽然好理解,但是没效率,后面看这个博客发现没有动态规划做了这个题 也是比较厉害. 转载地址: http ...
- bluecms v1.6 代码审计
0x01 使用seay源代码审计系统进行审计 扫描到了很多个可疑漏洞,不过工具都有一定的误报,下面我们就逐个进行验证 0x02 /ad_js.php SQL注入漏洞 查看源码,我们发现程序通过GET方 ...
- js获取当前地址信息
var url = window.location.href; //获取当前窗口的Url; 结果:http://localhost:61768/Home/Index?id=2&age=18 v ...