上一篇简单的写了观察者模式例子和实现思路,对观察者模式只是有了大致的了解,设计模式一般都比较抽象,实际运用需要根据需求来设计、重构,这篇就看看书上的例子,加深理解。

实现说明
游戏事件系统的实现
//游戏事件系统的实现
public enum ENUM_GameEvent{None = 0,EnemyKilled = 1, //敌方单位阵亡SoldierKilled = 2,//玩家单位阵亡SoldierUpgate = 3,//玩家单位升级NewStage = 4 //新关卡
}//游戏事件系统
public class GameEventSystem:IGameSystem{private Dictionary<ENUM_GameEvent,IGameEventSubject> m_GameEvents= new Dictoinary<ENUM_GameEvent,IGameEventSubject>();public GameEventSystem(PBaseDefenseGame PBDGameObject):base(PBDGame){Initialize();}//释放public override void Release(){m_GameEvents.Clear();}//为某一主题注册一个观察者public void RegisterObserver(ENUM_GameEvent emGameEvent,IGameEeventObserver Observer){//获取事件IGameEventSubject Subject = GetGameEventSubject(emGameEvent);if(Subject != null){Subject.Attach(Observer);}}//注册一个事件private IGameEventSubject GetGameEventSubject(ENUM_GameEvent emGameEvent) {//是否已经存在if(m_GameEvents.ContainKey(emGameEvent())return m_GameEvents(emGameEvent);//产生对应的GameEventIGameEventSystem pSubJect = null;switch(emGameEvent){case ENUM_GameEvent.EnemyKilled:pSubject = new EnemyKilledSubject();break;case ENUM_GameEvent.SoldierKilled:pSubject = new EnemyKilledSubject();break;//...根据枚举,确定主题事件default:Debug.LogWarning("还没有针对" +emGameEvent+"指定要产生的Subject类");return null;}//加入后并返回m_GameEvents.Add(emGameEvent,pSubject);return pSubject;}//通知一个GameEvent更新public void NotifySubject(ENUM_GameEvent emGameEvent,System.Object Param){//是否存在if(m_GameEvents.ContainsKey(emGameEvent) == false){return;}m_GameEvents[emGameEvent].SetParam(Param);}
}

游戏事件系统类使用了字典来管理所有游戏事件主题
新增时,针对每一个游戏事件产生对应的主题后加入容器内容,并保证一个游戏事件只存在一个主题对象。

RegisterObserver 方法用于其他系统向游戏事件系统订阅主题,
调用时传入指定的游戏事件及观察者类对象。

当某游戏事件触发时,通过通知主题更新NotifySystem方法,就能通知所有订阅该游戏事件主题的观察者

游戏事件主题,观察者接口
public abstract class IGameEventSubject{//观察者private List<IGameEventObserver> m_Observer = new List>IGameEventObserver>(); //发生事件时附加的参数//加入public void Attach(IGameEventObserver theObserver){m_Observers.Add(theObserver);}//取消public void Detach(IGameEventObserver theObserver){m_Observer.Remove(theObserver);}//通知public void Notify(){foreach(IGameEventObserver theObserver in m_Observers)theObserver.Update();}//设置参数public virtual void SetParam(System.Object Param){m_Param = Param;}
}public abstract class IGameEventObserver{public abstract void Update();public abstract void SetSubject( IGameEventSubject Subject );
}

类中定义一个List泛型容器,来管理订阅该主题的观察者,并提供SetParam方法来设置每一个游戏事件所需提供的内容。

观察者接口也只是简单的设置主题,和更新操作。
这样,观察者设置好主题,当主题更新时,主题就会通知它的每个观察者也进行对应的更新。

完成各个游戏事件主题及观察者

以下是4个游戏事件主题

1、敌人角色阵亡
2、玩家角色阵亡
3、玩家角色升级
4、进入新关卡

敌人角色阵亡
public class EnemyKilledSubject  : IGameEventSubject {private int m_KilledCount = 0;private IEnemy = m_Enemy = null;public EnemyKilledSubject(){}//获取对象public IEnemy GetEnemy(){return m_Enemy;}//当前敌人单位阵亡数public int GetKilledCount(){return m_KilledCount;}//通知敌人单位阵亡public override void SetParam(System.Object Param){base.SetParam(Param);m_Enemy = Param as IEnemy;m_KilledCount ++;//通知Notify();}
}

敌人角色阵亡,会发出通知,将阵亡的而敌人角色使用SetParam方法传入,在内容增加计时器,提供给观察者查询。

对应的3个观察者
//UI观察者Enemy阵亡事件
public class EnemyKilledObserverUI : IGameEventObserver {private EnemyKilledSubject m_Subject = null;private PBaseDefenseGame m_PBDGame = null;//设置观察者public EnemyKilledObserverUI(PBaseDefenseGame PBDGame){m_PBDGame = PBDGame;}//通知Subject被更新public override void SetSubject(IGameEventSubject Subject){m_Subject = Subject as EnemyKilledSubject;}//通知Subject被更新public override void Update(){m_PBDGame.ShowGameMsg("敌方单位阵亡");}
}//成就观察Enemy阵亡事件
public class EnemyKilledObserAchievement : IGameEventObserver{private EnemyKilledSubject m_Subject = null;private AchievementSystem m_AchievementSystem = null;public EnemyKilledObserAchievement(AchievementSystem theAchieventSystem){m_AchievementSystem  = theAchieventSystem;}//设置观察者的主题public override void SetSubject(IGameEventSubject Subject){m_Subject = Subject as EnemyKilledSubject;}//通知主题更新public override void Update(){m_AchievementSystem.AddEnemyKilledCount();}
}
//关卡分数观察者
public class EnemyKilledObserverStageScore:IGameEventObserver{private EnemyKilledSubject m_Subject = null;private StageSystem m_StageSystem = null;public EnemyKilledObserverStageScore(StageSystem theStageSystem){m_StageSystem = theStageSystem;}//设置观察者...//设置主题更新public override void Update(){m_StageSystem.SetEnemyKilledCount(m_Subject.GetKilledCount());}
}

以上即为一个主题与观察的实现,可以看到,每个观察者都有不同游戏系统的对象引用,
但是它们都被同一个主题(敌人被击杀事件)管理,主题一旦更新(信息更新),
就通知每个观察者,让它们(不同的游戏系统)做不同的功能操作。
当需要更多具体的细节功能时 如:if条件限制,可以在Update的方法里添加

剩下的事件主题和观察者根据上面的设计模板和思路实现即可,这里不再一一列出了,有兴趣可以购买作者的这本书来看看,或者去github下载源码= 。 =
https://github.com/sttsai/PBaseDefense_Unity3D

使用观察者模式的优点

成就系统以游戏事件为基础,记录每个游戏事件发生的次数以及时间点,作为成就项目的判断依据。当一个游戏事件会触发时,可能存在其他系统需要使用同一个游戏事件。

因此,加入了以观察者模式为基础的游戏事件系统,就可以有效解除“游戏事件的发生”与有关的“系统功能调用”之间的绑定。

这样游戏事件发生时就不必理会后续的处理工作,而是交给游戏事件主题负责调用观察者/订阅者。此外,也能同时调用多个系统同时处理这个事件引发的后续操作。

注意的

双向和单向信息通知:
在社交网页上,如微博当通过关注、订阅来建立观察者和主题的关系。它们之间互相关注,就是双向的信息通知,同时扮演观察者和主题的角色。

类过多的问题:
一个主题一般会有多个观察者,如果一个观察者就是一个类时,随着项目的开发就会造成大量的类,这反而是个缺点。因此可以把类对象转换使用回调函数,然后将功能相似的“回调函数”以同一个类来管理,就能减少类过多的问题。

命令模式与观察者模式的关系
这两个模式都着重于“发生”与“执行”这两个操作消除解耦的模式。当观察者的主题只有一个观察者时,就非常像命令着模式。
但还是有一些差异可以分辨出两个模式应用的时机:
命令模式:重点是对命令的管理,应用的系统对于发出的命令有增、删、改、记录、排序、撤销 等操作的需求
观察者模式:对于“观察者/订阅者”进行管理,意思是观察者可以在 系统运行时间决定订阅或退订等操作,让“执行者(观察者/订阅者)”可以被管理。

Unity3D设计模式学习之观察者模式(二)相关推荐

  1. Unity3D 设计模式学习之观察者模式

    游戏里成就系统可以使用观察者模式.要实现成就系统之前,一般需要企划单位先将需要的成就事件列出来,并在项目完成到某个段落之后,才开始加入实现开发中. 大致实现逻辑: 先定义"游戏事件" ...

  2. 设计模式学习笔记之二:观察者模式

    观察者模式定义了对象之间一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新. Observer package com.singland.dp.observer;publ ...

  3. 设计模式学习笔记(二十一:访问者模式)

    1.1概述 表示将一个作用于某对象结构中的各个元素的操作.它可以在不改变各个元素的类的前提下定义作用于这些元素的新操作.这就是访问者模式的定义. 编写类的时候,可能在该类中编写了若干个实例方法,该类的 ...

  4. 设计模式学习笔记(二)工厂模式、模板模式和策略模式的混合使用

    一.工厂模式(Factory pattern) 工厂模式又叫做工厂方法模式,是一种创建型设计模式,一般是在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型. 1.1 工厂模式介绍 工厂模式是 ...

  5. 拿捏大厂面试,设计模式学习笔记(二)工厂模式、模板模式和策略模式的混合使用

    一.工厂模式 工厂模式又叫做工厂方法模式,是一种创建型设计模式,一般是在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型. 1.1 工厂模式介绍 工厂模式是Java 中比较常见的一种设计模式 ...

  6. uml图中的各种箭头_设计模式学习笔记(二):UML与面向对象设计原则

    1 UML 1.1 UML UML(Unified Modeling Language)是统一建模语言,1997年11月UML1.1版本提交给OMG并正式通过,成为建模语言的个那个也标准.2003年6 ...

  7. 设计模式学习笔记-观察者模式(转)

    http://www.cnblogs.com/wangjq/archive/2012/07/12/2587966.html 1. 概述 有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系, ...

  8. 设计模式学习笔记(二十二:备忘录模式)

    1.1概述 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以将该对象恢复到原先保存的状态.这就是备忘录模式的定义. 对象的状态依赖于它的变量的取值情况,对象在 ...

  9. Java-马士兵设计模式学习笔记-观察者模式-读取properties文件改成单例模式

    一.概述 1.目标:读取properties文件改成单例模式 二.代码 1.Test.java 1 class WakenUpEvent{ 2 3 private long time; 4 priva ...

最新文章

  1. c语言课程思政教案设计,设计类专业课程思政教学案例及教学设计
  2. 小波变换和motion信号处理(三)(转)
  3. redmine 邮件发送问题修复
  4. D-query SPOJ - DQUERY (莫队算法裸题)
  5. Tapable.plugin is deprecated. Use new API on `.hooks` instead
  6. 通过ajax提交到url路由
  7. 自动摘要php,phpcms修改手动摘要255字符、自动摘要200字符及取消自动摘要
  8. 崇天老师python123测验6_嵩天老师python123测验1: Python基本语法元素 (第1周)
  9. c语言指针的地址存放,c语言 - *指针 和 地址
  10. selenium(java)遇到的问题
  11. qwt的安装和移植-
  12. C++中algorithm头文件中一些函数使用记录
  13. CSS3+JS制作的一款图标任意拖动,并且可以放在文件夹中
  14. php中控车牌识别push协议,2、实时车牌识别上传及返回
  15. 《鸟哥 Linux 私房菜:基础版》阅读笔记
  16. 国家地区代号与英文名对应表
  17. win7 计算机打不开搜狗,Win7系统中搜狗输入法不见了如何解决
  18. 模糊控制理论理解与综述
  19. python第六周拼图_python – 解决n-queen拼图
  20. uniapp中使用svga动画

热门文章

  1. PyTorch中linspace的详细用法
  2. 在JavaScript中时间戳
  3. JVM常见的垃圾回收器
  4. 利用WeX5平台实现单图片上传功能
  5. Cesium加载天地图山东WMTS服务(weixin公众号【图说GIS】)
  6. 千元内有什么性价比蓝牙耳机?盘点几款平价好用的蓝牙耳机
  7. 硅谷来信2,156,扎克伯格的5宗个人恩怨
  8. excel中最后几位数值为0处理方法
  9. [AWT] BorderLayout
  10. 用Python实现简易音乐播放器(mp3类型)3