初级知识六——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 ...
随机推荐
- [NewLife.Net]单机400万长连接压力测试
目标 对网络库NewLife.Net进行单机百万级长连接测试,并持续收发数据,检测网络库稳定性. [2020年8月1日晚上22点] 先上源码:https://github.com/NewLifeX/N ...
- pageHelper使用时的注意点
1 在pom.xml中导入相关的依赖(注意版本问题,报错十有八九是因为版本问题) <dependency> <groupId>com.github.pagehelper< ...
- 【av68676164(p48-p50】虚拟内存管理(1)
7.3.1 页式虚拟内存管理概念 物理内存(即实内存)管理 特点 缺点 1 源程序直接使用内存的物理地址 程序间容易访问冲突 2 程序必须全部装入内存才能运行 内存太小程序无法运行 3 程序占用连续的 ...
- 微信小程序之回到顶部的两种方式
第一种:使用view标签形式回到顶部 WXML: <image src='../../img/button-top.png' class='goTop' hidden='{{!floorstat ...
- 阿里出品的最新版 Java 开发手册,嵩山版,扫地僧
说起嵩山,我就想起乔峰,想起慕容复,以及他们两位老爹在少林寺大战的场景.当然了,最令我印象深刻的就是那位默默无闻,却一鸣惊人的扫地僧啊.这次,阿里出品的嵩山版 Java 开发手册的封面就有一个扫地僧, ...
- C#LeetCode刷题之#326-3的幂(Power of Three)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3867 访问. 给定一个整数,写一个函数来判断它是否是 3 的幂次 ...
- K8s集群verification error" while trying to verify candidate authority certificate "kubernetes"
问题内容 because of "crypto/rsa: verification error" while trying to verify candidate authorit ...
- 认识与学习BASH①——鸟叔的Linux私房菜
文章目录 认识与学习BASH① 认识BASH 壳程序 多种shells Bash shell 的功能 type :查询指令是否为Bash shell 的内置指令 指令的换行输入和快速删除 Shell的 ...
- Python多进程实现并行化随机森林
文章目录 1. 前言 2. 随机森林原理 3.实现原理 3.1并行化训练 3.1.1训练函数 3.1.2 单进程训练函数 生成数据集模块--生成部分数据集 单进程训练函数代码 3.2 并行化预测 3. ...
- 学长小清新题表之UOJ 180.实验室外的攻防战
学长小清新题表之UOJ 180.实验室外的攻防战 题目描述 时针指向午夜十二点,约定的日子--\(2\)月\(28\)日终于到来了.随着一声枪响,伏特跳蚤国王率领着他的跳蚤大军们包围了 \(picks ...