在Unity中使用事件/委托机制(event/delegate)进行GameObject之







   一对多的观察者模式机制有什么缺点?
  
  如果你对如何在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 Dictionarystring, EventHandler eventTable;
  protected INotificationCenter()
  {
  eventTable = new Dictionarystring, 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 Dictionarystring, EventHandler handlers;
  void Awake() {
  handlers = new Dictionarystring, EventHandler();
  center = NotificationCenter.GetInstance();
  }
  void OnDestroy() {
  foreach (KeyValuePairstring, 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);
  }
  }



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值