【Unity3D技巧】在Unity中使用事件/委托机制(event/delegate)进行GameObject之间的通信 (二) : 引入中间层NotificationCenter
作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明。如果你喜欢这篇文章,请点【推荐】。谢谢!

一对多的观察者模式机制有什么缺点?
想要查看完整源代码,还是访问这个项目的GitHub:https://github.com/MrNerverDie/Unity-Flappy-Bird
如果你对如何在Unity中使用事件/委托机制还不太了解,建议您查看我的前一篇文章:【Unity3D技巧】在Unity中使用事件/委托机制(event/delegate)进行GameObject之间的通信
在前一篇博客里面,我们写到:【Unity3D技巧】在Unity中使用事件/委托机制(event/delegate)进行GameObject之间的通信,其中使用了EventHandler这个委托作为通用的事件类型,实现了一对多的观察者模式。但是这样做有什么缺点呢?我们还是举前文所说的小鸟撞上管道为例:

在这里面,小鸟撞倒管道时,小鸟会发送一个 产生碰撞的 消息传送给所有观察者,那么,如果我们新加入一个名为天鹅,它也能在天上飞,那么我们就要在它的类内部实现一个同样功能的 产生碰撞的 消息传送给所有观察者,这样就产生了代码重复,软件中解决代码重复的问题一般使用的事引入中间层的办法,所以我仿照Cocos2d-x中的CCNotificationCenter写了一个CCNotificationCenter来存储各种消息并转发来当作中间层。
引入中间层 -- NotificationCenter
NotificationCenter基本的设计思路是基于MessageDispatcher模式的,即使用一个字典(Dictionary)来记录各种需要转发的信息,以及这些信息的观察者,然后再恰当的时候进行消息的转发。NotificationCenter还应当提供观察者订阅和取消订阅的方法。
NotificationCenter是基于单件模式的,它在第一次被调用GetInstance方法时被初始化的,使用单件的原因是要让NotificationCenter的生命期比任何一个观察者都长,这样才不会出现NotificationCenter为空的情况。
在下面的代码里,我把INotificationCenter做成抽象类的原因是:希望通过这个继承这个类来创建多个子类,比如可以创建UINotificationCenter,BattleNotificationCenter,TradeNotificationCenter。来进行消息的分组。
下面我把自己的代码分享一下,供大家参考:
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic; // NotificationCenter的拓展类,在这里弄出多个INotificationCenter的子类,
// 分别处理不同的消息转发,便于消息分组
public class NotificationCenter : INotificationCenter
{
private static INotificationCenter singleton; private event EventHandler GameOver;
private event EventHandler ScoreAdd; private NotificationCenter()
: base()
{
// 在这里添加需要分发的各种消息
eventTable["GameOver"] = GameOver;
eventTable["ScoreAdd"] = ScoreAdd;
} public static INotificationCenter GetInstance()
{
if (singleton == null)
singleton = new NotificationCenter();
return singleton;
}
} // NotificationCenter的抽象基类
public abstract class INotificationCenter
{ protected Dictionary<string, EventHandler> eventTable; protected INotificationCenter()
{
eventTable = new Dictionary<string, EventHandler>();
} // PostNotification -- 将名字为name,发送者为sender,参数为e的消息发送出去
public void PostNotification(string name)
{
this.PostNotification(name, null, EventArgs.Empty);
}
public void PostNotification(string name, object sender)
{
this.PostNotification(name, name, EventArgs.Empty);
}
public void PostNotification(string name, object sender, EventArgs e)
{
if (eventTable[name] != null)
{
eventTable[name](sender, e);
}
} // 添加或者移除了一个回调函数。
public void AddEventHandler(string name, EventHandler handler)
{
eventTable[name] += handler;
}
public void RemoveEventHandler(string name, EventHandler handler)
{
eventTable[name] -= handler;
} }
对观察者进行抽象化 -- 引入Observer
在加入了NotificationCenter之后,我们要面对的下一个问题就是,我们的每一个观察者都需要在自己的Start方法中添加回调函数,在OnDestroy方法中取消回调函数,那么,我们可以把这部分的代码抽象在一个Observer组件中,使用另一个字典记载下所有的该GameObject注册的回调函数,在Observer的OnDestroy方法里面一次全部取消订阅。代码如下:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System; public class Observer : MonoBehaviour {
private INotificationCenter center;
private Dictionary<string, EventHandler> handlers; void Awake() {
handlers = new Dictionary<string, EventHandler>();
center = NotificationCenter.GetInstance();
} void OnDestroy() {
foreach (KeyValuePair<string, EventHandler> kvp in handlers) {
center.RemoveEventHandler(kvp.Key, kvp.Value);
}
} public void AddEventHandler(string name, EventHandler handler) {
center.AddEventHandler(name, handler);
handlers.Add(name, handler);
}
}
【Unity3D技巧】在Unity中使用事件/委托机制(event/delegate)进行GameObject之间的通信 (二) : 引入中间层NotificationCenter的更多相关文章
- 【Unity游戏开发】用C#和Lua实现Unity中的事件分发机制EventDispatcher
一.简介 最近马三换了一家大公司工作,公司制度规范了一些,因此平时的业余时间多了不少.但是人却懒了下来,最近这一个月都没怎么研究新技术,博客写得也是拖拖拉拉,周六周天就躺尸在家看帖子.看小说,要么就是 ...
- JavaScript中的事件委托机制跟深浅拷贝
今天聊下JavaScript中的事件委托跟深浅拷贝 事件委托 首先呢,介绍一下事件绑定 //方法一:通过onclick <button onclick="clickEvent()&qu ...
- Javascript事件模型系列(二)事件的捕获-冒泡机制及事件委托机制
一.事件的捕获与冒泡 由W3C规定的DOM2标准中,一次事件的完整过程包括三步:捕获→执行目标元素的监听函数→冒泡,在捕获和冒泡阶段,会依次检查途径的每个节点,如果该节点注册了相应的监听函数,则执行监 ...
- 怎么理解js中的事件委托
怎么理解js中的事件委托 时间 2015-01-15 00:59:59 SegmentFault 原文 http://segmentfault.com/blog/sunchengli/119000 ...
- javascript中的事件委托
这几天看到一个面试题,大概就是,让你给1000个li都添加一个click事件,应该怎么添加?大多数人第一开始的感觉可能就是,每个li上边都添加一个呗,那要是这样的话,估计面试的时候就会GG了,这里就是 ...
- js实例分析JavaScript中的事件委托和事件绑定
我们在学习JavaScript中,难免都会去网上查一些资料.也许偶尔就会遇到“事件委托”(也有的称我“事件代理”,这里不评论谁是谁非.以下全部称为“事件委托”),尤其是在查JavaScript的事件处 ...
- JQuery中的事件委托
JQuery 中的事件委托 定义 事件委托就是利用冒泡的原理,把事件加到父级上,通过判断事件来源的子集,执行相应的操作,事件委托首先可以极大减少事件绑定次数,提高性能:其次可以让新元素的子元素也可以拥 ...
- js中的事件委托或是事件代理
JavaScript(jQuery)中的事件委托 https://www.cnblogs.com/zhoushengxiu/p/5703095.html js中的事件委托或是事件代理详解 https: ...
- 简单说 JavaScript中的事件委托(下)
说明 上次我们说了一些,关于 JavaScript中事件委托的 基础知识,这次我们继续来看. 解释 先来一段代码 <!doctype html> <html lang="e ...
随机推荐
- Shell 语法之输入输出
Linux 使用文件描述符标识每个文件对象.文件描述符是一个非负整数,可以唯一地标识会话中打开的文件.每个进程中最多可以有9个打开文件的描述符. Linux 标准文件描述符 文件描述符 缩写 描述 0 ...
- eclipse中配置tomcat后,运行jsp时出现Server Tomcat v7.0 Server at localhost failed to start.
最近在进行jsp开发学习,在配置上还是遇到很多问题. 在连接好数据库后,写了第一个jsp测试页面,结果在运行eclipse中运行toamcat时出现了错误提示:Server Tomcat v7.0 S ...
- Android中Webview使用自定义的javascript进行回调
先说为什么需要讨论这个问题. 现在很多的手机应用,都可能会直接嵌入一个web页面.这样做的好处:一个是功能更新方便,维护起来容易,只需要维护服务器的页面即可,不需要更新客户端:另一个是功能通用,不仅a ...
- 无障碍网页设计(WCAG2.0)
无障碍化是指无论健全人还是残疾人,年轻人还是老年人都可以平等地获取互联网上的信息和服务.无障碍化网站建设不单可以增加网站的受益群体,更是一个有情怀.有担当的互联网企业的责任,也是一个互联网从业人员应该 ...
- WEB UI 整理
当下对于网站前段开发人员来说,很少有人不使用一些JS框架或者WEB UI库,因此这些可以有效提高网站前段开发速度,并且能够统一开发环境,对于不同浏览器的兼容性也不需要程序员操心,有了这些优点,当然大家 ...
- [转]CSS,font-family,常用网页字体
http://www.zreading.cn/ican/2014/10/css-font-family/ CSS,font-family,好看常用的中文字体 2014-10-14 例1(小米米官网): ...
- GCD与block
GCD技术多线程编程的三个技术 NSThread NSOperation GCD1.GCD(Grand central Dispatch:宏大的中央调度) 1) 是用纯C语言实现的.提 ...
- adb error: device not found
我的adt无法调试一个平板,我的手机却能调试,百度了好多次,折腾了两个周,换了几个版本的adt,都不成. 就在刚才,我在设备管理器找到那个设备Samsung xxx,点更新驱动,自动搜索,那个设备就变 ...
- powershell玩转sqlite数据库
脚本经常需要处理文本,有时候是行列整齐文本.那么powershell脚本处理行列文本有几种方法呢?一种是excel,另外的一些是?access?sqlite? sqlite是一个很小巧的,很方便嵌入到 ...
- CSS控制XML与通过js解析xml然后通过html显示xml中的数据
使用CSS控制XML的显示 book.css bookname{ display:block;color:Red} author{ display:block;font-style:italic} p ...