RPG游戏中的设计模式之策略模式

上篇博客分析了游戏中的单例模式,这篇博客分析一下游戏中使用到的策略模式。

策略模式

先给出策略模式的定义

定义

定义了算法族,分别封装起来,让他们之间可以相互替换,此模式的算法可以独立于使用它的客户。[1]P24

可以将算法族理解为同一个算法的不同变体,典型的策略模式其实就是客户可以使用同一个算法的不同变体,使用的过程中可以更换。

适用性

以下情况可以使用策略模式 1. 需要使用一个算法的不同变体,如本文的游戏,Hero会使用不同的行为。 2. 许多相关的类仅仅行为有异,策略模式提供了一种用多个行为中的一个行为配置一个类的方法

上面对策略模式的描述说的可能比较抽象,下面我们还是结合游戏分析一下策略模式。

游戏中的客户与算法族

游戏中的客户就是角色(Roles),而算法族就是发射子弹的行为。 打开VS工程中的类图ClassDiagram1.cd,我们可以看到。

客户(所有角色)

这些角色,包括英雄,怪兽。双击Roles和Hero可以看到源码:

Roles : RoAndMi{//拥有发射子弹的行为protected FireBehavior fireBehavior;(FireBehavior fireBehavior){this.fireBehavior = fireBehavior;}调用fireBehavior.Fire()实现真正的发射(){fireBehavior.Fire();}…}public class Hero : Roles{public Hero(int x, int y, int xspeed, int yspeed, int life, bool good): base(x, y, myImage.Width, myImage.Height, xspeed, yspeed, life, good){blb = new BloodBar(x,y, life);//使用FireOneMissilesByHero行为SetFireBehavior(new FireOneMissilesByHero(this));} }

游戏中所有角色都有个发射子弹的行为FireBehavior(继承自Roles),但是每个角色拥有的行为又不一样,如EnemyOne拥有FireMissileOneByEnemy,Hero拥有FireOneMissilesByHero,并且在程序运行过程中可以更换发射行为为FireThreeMissilesByHero,也就是说客户使用了FireBehavior的不同变体,并且可以通过调用SetFireBehavior方法更换发射子弹的行为,实现了不同算法变体的互换。

算法族(角色的行为)

这些发射子弹的行为,由客户Roles来使用。双击FireBehavior就可以看到起源码:

FireBehavior{();}

角色通过FireBehavior中的Fire方法实现真正的发射子弹的行为。

这里为什么没有使用接口,而使用了抽象类 在游戏的实现过程中,发射子弹的行为与角色相关,所以在发射的时候,需要先判断是哪个角色,所以FireBehavior里面需要成员变量Roles,而接口是不能包含成员变量的,所以需要使用抽象类。仔细分析一下游戏的源码就会非常清楚为什么用抽象类了。 关于在设计过程中优先采用抽象类还是接口,这个问题要考虑很多东西,我不敢妄作评论,在具体设计过程中,我个人更加倾向于优先采用抽象类,而不是接口。

类图

看一下他们的类图,会更加清晰的看到他们之间的关系

角色拥有发射子弹的行为,并且可以通过SetFireBehavior()方法更换发射子弹的行为。

设置初始行为

策略模式中,设置初始行为一般都是通过构造函数实现。打开Hero.cs源码:

public class Hero : Roles{public Hero(int x, int y, int xspeed, int yspeed, int life, bool good): base(x, y, myImage.Width, myImage.Height, xspeed, yspeed, life, good){blb = new BloodBar(x,y, life);//使用FireOneMissilesByHero行为作为初始行为SetFireBehavior(new FireOneMissilesByHero(this));}…. }

我们可以看到,,通过构造函数实现设置初始行为。

更换行为

游戏中,当英雄的经验值>100后,子弹威力变大,能够同时发射3个子弹,在HitCheck类中我们可以看到,通过SetFireBehavior方法更换行为(同一算法的不同变体)

//更换行为,升级装备 if (myHero.score > 100)myHero.SetFireBehavior(new FireThreeMissilesByHero(myHero));//策略模式游戏中为什么要用策略模式

游戏中,英雄和敌人有个发射子弹的行为FireBehavior(继承自Roles),但是每个角色的行为都不一样,而且同一个角色在游戏中的发射子弹的行为也会发生变化,如英雄一开始每次只能发射一颗子弹,后来由于经验值增加,每次可以发射多个子弹,发射行为在游戏中会发生变化,在程序中需要更换行为,这里就可以使用策略模式,将不同的发射子弹的行为封转为算法族,让他们可以相互替换。使用策略模式,能够降低客户和算法族之间的耦合性,如果以后游戏要升级,添加其他的发射子弹行为就非常容易,能够使系统具有良好的扩展性和维护性。

OO原则

单例模式中,由于只有一个类,体现不出什么OO设计原则,在策略模式中,就可以体现出一些重要的OO设计原则。

针对接口编程,而不是针对实现编程

[1]P11 其实整个设计模式的一个核心思想就是针对接口编程,而不是针对实现编程。这里的接口,并不是java或者C#中的interface,这里的接口其实指的是超类型,包括接口和抽象类,核心思想就是多态。

看一下上面的类图

Roles的成员变量fireBehavior

//使用发射子弹的行为protected FireBehavior fireBehavior;

和SetFireBehavior方法:

(FireBehavior fireBehavior){this.fireBehavior = fireBehavior;}每天告诉自己一次,『我真的很不错』

RPG游戏中的设计模式之策略模式

相关文章:

你感兴趣的文章:

标签云: