游戏中的设计模式(1)--观察者模式

       作为本系列文章的第一篇,笔者在此想表达一下个人对于设计模式的一些理解。因此笔者自问自答几个问题。1,什么是设计模式?2,在软件快速迭代的今天,设计模式是否重要?3,四人帮提出了23个设计模式,是不是设计问题无出其右?4,设计模式和语言是什么关系?5,设计模式和面向对象的关系?

1,什么是设计模式?
      拿百度谷歌一下,可以找到各种各样的回答,只是很多的回答实在是会让人找不到北,模式这个词确实很高大上,因此常常出没于学术界。针对设计模式这个问题,笔者对设计模式的理解是,设计模式可以认为是解决某一类问题的通用方案,为什么是通用的呢,其实GOF没有创造任何新的设计方法,相反他们是将前人的软件设计方法进行了充分的归类总结,得到了最著名的23条设计模式,因此可以说这些设计模式在有一个响当当的名字之前已经有很多的人在使用。

2,在软件快速迭代的今天,设计模式是否重要?
      重要与否,在于使用者对其的态度,设计问题本来就没有一个充分必要条件,并且在一个快速迭代的开发周期内,结果或许比过程更重要,毕竟玩家,策划不care你的架构是否优美,结构是否灵活可扩展。但是从一个软件设计者(这title不错,请不要叫我程序员)的角度而言,你可能需要一定的美感(攻城狮也是有追求滴),当然,最重要的是你需要架构具有足够的可扩展性(很飘渺的一个词就像高内聚低耦合一样,只可意会不可言传)。可扩展和藕合可谓是一对天敌,如果你不介意藕合性,设计模式可能是没有什么意义的,否则那你真真需要去找找四人帮了。

3,四人帮提出了23个设计模式,是不是设计问题无出其右?
     这种问题的答案肯定是否定的,高考选择题的诀窍啊,GOF毕竟历史比较久远了,GOF的23种模式是经典,但是随着软件的发展,也出现了很多新的设计模式。比如,2007年google发表了一篇震惊我们攻城界的文章,提出了Map-Reduce模式,有人认为这是个算法,也有人认为这是个设计模式,whatever,MR确实真真推动了行业的发展。那么C/S,B/S,MVC,MVP是不是设计模式呢,应该是吧,笔者个人认为(也可以认为是体系结构)。

4,设计模式和语言以及面向对象是什么关系?
     这之间好像没有半毛钱的关系,之所以所有关于设计模式的书籍都是用Java语言来解释的,是因为Java语言面向对象的特性很容易表述设计模式要解决的问题,并且Java的语法和C/C++相似,让绝大部分人都能很容易理解,面向对象的Java语言很容易表述设计模式要解决的问题,其实这里也隐含了一种意思,面向对象的语言更容易使用设计模式的方法来解决问题。设计模式本身讲究的是对问题的抽象,而面向对象也是为了对问题的抽象,试想如果使用C语言来解释设计模式,单就是函数指针的定义估计就会吓跑了无数的阅读者。

下面来分析本文要讨论的一个设计模式:观察者模式。观察者模式,又称发布-订阅者模式,是GOF提出的23种设计模式之一,属于行为型模式的一种,用于解决不同模块之间的通信问题。观察者模式中的角色有2个:
      (1)主题(Subject):可以理解为消息(及必布者)。
      (2)观察者(Observer):消息的接受者(消费者)。
在一个标准的观察者模式中,主题和观察者之间的相互依赖是抽象的,因此他们之间的关系可以使用如下UML类图来进行表示
游戏中的设计模式(1)--观察者模式_第1张图片


从图中可以看出当一个主题可以同时拥有多个观察者,当主题发生变化是通知所有的观察者,该模式解决这样一类问题:当模块B依赖模块A的数据时,模块B需要知道模块A的数据发生改变,并且使用抽象(DIP)的机制使得的模块间的耦合性大大降低。当不使用观察者模式时,模块B需要自己去定时检测模块A的数据是否发生变化,如此不仅增加了代码的复杂度,模块之间的耦合性也会变得更加复杂。

上面简要介绍了观察者模式的基本原理,因为网上有对其非常充分的讲解,故而此处不做过多分析,下面我们来看一下在游戏中如何大量使用该模式来将解耦模块之间的关系。考虑一个游戏中的战斗单位,且称之为Boss,Boss有一个非常重要的信息血量(HP),在一场Boss战中会有多个模块依赖于该Boss的血量变化:
(1) UI模块:Boss的血条需要实时显示当前剩余的血量。
(2) Boss技能:当血量减少到一定值时会触发相应的技能(大招,召唤小怪等)。
(3) AI模块:当对方的Boss血量达到某个值时,可以触发某类AI。
(4) 更多的模块可能会依赖于HP值。

如此多的模块依赖于HP值的变化,因此需要十分谨慎的处理模块间的依赖关系,否则极要可能使得模块间的耦合性异常复杂(当然,如果系统不复杂耦合不会是什么大问题),那么在真实的项目中是如何处理这种依赖关系的呢? 观察者模式,但是我们不是使用标准的观察者模式,是观察者模式的一个变种,如下图所示:
游戏中的设计模式(1)--观察者模式_第2张图片

其中的Handler是指我们定义的python函数(类函数),Boss是我们Member类的一个实例对象,Handler可以是技能模块,AI模块,UI模块等任意模块的函数,只要其函数定义符合 def function(event)格式即可(因为python是脚本语言,因此也是某种意义的抽象),其中evntKey是该函数监听该对象身上的事件,如对于HP变化的监听,我们定义为M_HP。当Member的HP发生改变是,主动调用dispatchEvent,所有注册了M_HP的接口都会被回调。

其实观察者模式是非常简单的一种模式,同时也是非常常用的模式之一,该模式适用于解决1对N单向消息传递类型的问题,上面HP的例子,我们使用该模式非常容易地解决了不同模块间的耦合问题,当然我们并未完成遵循标准观察者模式的体系结构,简单的变形,反而更利于具体问题的解决。





你可能感兴趣的:(游戏中的设计模式(1)--观察者模式)