游戏开发中常用的设计模式
使用设计模式来提高程序库的重复利用性是大型程序项目开发必须的。但是在“四人帮”的设计模式概述中提到了23种标准设计模式,不但难以记住,而且有些设计模式更多的适用于应用程序开发,对游戏项目引擎设计并没有很多的利用价值。
观察者Observer
它将对象与对象之间创建一种依赖关系,当其中一个对象发生变化时,它会将这个变化通知给与其创建关系的对象中,实现自动化的通知更新。
游戏中观察者的适用环境有:
- UI控件管理类。
当我们的GUI控件都使用观察者模式后,那么用户的任何界面相关操作和改变都将会通知其关联对象—–我们的UI事件机。 - 动画管理器。
很多时候我们在播放一个动画桢的时候,对其Frame有很大兴趣,此时我们设置一个FrameLister对象对其进行监视,获得我们关心的事件进行处理是必须的。 技能系统。
在这执行的过程中角色可能发生种种意外(主要是ARPG比较容易出现),常见的事件比如角色死亡、切换地图、打断技能等,如果此时还在执行某些效果,我们需要将其正确的处理掉。一种直观的办法是将处理的操作封装到一个角色对象上的一个函数中,通过调用这个函数来完成清理,各个模块需要清理的就把清理相关代码加到这个函数中来。但是这种做法并不理想,首先一堆需要清理的功能放到一个函数中肯定不好看,另外个人觉得写起来别扭也容易漏掉,对于多个事件我们还得封装到不同的函数里面去,坏处一堆堆谁试谁知道。
而通过观察者模式来进行管理,把角色对象定义成一个Subject,而具体的效果流程定义为Observer,这样一些持续性效果在开始之前,把自己加入到Subject上的某个事件的观察者列表中,角色对象由于状态改变而发出事件通知的时候,只需执行Notity(event),即可广播给所有关心这个事件的Observer对象(调用该对象上的OnEvent),这样每个效果流程内部只需要实现OnEvent并且添加处理代码就完成了整个过程,要比前者简洁漂亮不少。
观察者伪代码:
// 被观察对象目标类
Class Subject
{
// 对本目标绑定一个观察者 Attach( Observer );
// 解除一个观察者的绑定 DeleteAttach( Observer );
// 本目标发生改变了,通知所有的观察者,但没有传递改动了什么
Notity()
{
For ( …遍历整个ObserverList …)
{ pObserver ->Update(); }
}
// 对观察者暴露的接口,让观察者可获得本类有什么变动GetState();
}
// 观察者/监听者类
Class Observer
{
// 暴露给对象目标类的函数,当监听的对象发生了变动,则它会调用本函数通知观察者
Void Update ()
{
pSubject ->GetState(); // 获取监听对象发生了什么变化
TODO:DisposeFun(); // 根据状态不同,给予不同的处理
}
}
非程序语言描述:
A是B的好朋友,对B的行为非常关心。B要出门,此时A给了B一个警报器,告诉B说:“如果你有事,立刻按这个警报器告诉我。”。结果B在外面遇上了麻烦,按下警报器(Update()),A就知道B出了事,于是就调查一下B到底遇到了什么麻烦(GetState()),当知道B原来是因为被人打了,于是立刻进行处理DisposeFun(),派了一群手下帮B打架。
当然关心B的人可以不止一个,C,D可能也对A很关心,于是B这里保存一个所有关心它的人的链表,当遇到麻烦的时候,轮流给每个人一份通知。
单件模式Singleton
单件模式的设计意图和作用是: 保证一个类仅有一个实例,并且,仅提供一个访问它的全局访问点。
游戏中适用于单件模式的有:
- 所有的Manger
在大部分的流行引擎中都存在着它的影子,例如SoundManager, ParticeManager等。 - 大部分的工厂基类
这一点在大部分引擎中还是见不到的,实际上,我们的父类工厂采用唯一实例的话,我们子类进行扩展时也会有很大方便。
单件模式伪代码: