(译)策略模式 [strategy pattern]
前言
在面向对象 [Object Oriented,以下简称 OO] 的世界中,有着几个基本概念:
抽象 [abstract],
继承 [inheritance],
封装 [encapsulate],
多态 [polymorphism]。
但对于某些情况,基本的OO概念仍不足以让程序具有强大的弹性,在面对修改的时候会让程序员痛不欲生。
于是乎,设计模式 [design pattern] 就呼之欲出了。
策略模式 [strategy pattern]
假象以下情况:
在 Gamer_伍兹 的领导下,一个游戏团队准备开发一个战斗游戏,游戏中有 步兵 [Infantry],骑兵 [Cavalry],枪兵 [Spearman],弓箭手 [Archer]。他们可以使用武器来攻击。
用基本的OO概念,可以设计出方案一:
Character {
useWeapon ( );
}
Character <--- Infantry
<--- Cavalry
<--- Spearman
<--- Archer
“<---”:继承于
在方案一中,Character是一个父类 [super class],它拥有useWeapon ( )方法。而Infantry等具体角色则继承于Character。
在这个情况下,方案一是可行的。
但是,精益求精的游戏总监 Gamer_伍兹 要求每个角色有自己的武器,例如,Infantry使用剑 [Sword],Calvary使用马 [Horse] [虽然不算正统的武器,但是很多情况下,敌人是死在马蹄下,而不是骑兵的刀锋下],Spearman使用长矛 [Spear],Archer使用弓箭 [Bow]。
这时候,方案一是不能够再用了,因为每个角色都拥有自己的武器,而每个武器需要自己独特的useWeapon( )方法。
于是有了基本OO概念的方案二,从方案一中衍生过来:将Character类中的useWeapon ( )方法作为抽象方法,再在具体的子类中实现各种useWeapon( )方法。
后来,追求完美的 Gamer_伍兹 有一个新的想法,在近身战中,弓箭手 [Archer] 也需要使用剑 [Sword] [总不能敌人都在砍自己时,弓箭手还得气定神闲地瞄准对方吧]。
这个情况下,支持方案二的程序员就不得不把Character类中的useWeapon ( )删掉,因为有的子类拥有一个以上的useWeapon( ),具体来说,useBow( )和useSword( )方法。另外,他还得在Archer类当中重写一次useSwrod ( )方法。
真的很麻烦!
这时候,经验老到的设计模式大师提出了一个模式——策略模式!
此时,方案三呼之欲出:
Character {
Weapon weapon;
useWeapon ( ); // 此方法调用Weapon的useWeapon ( )方法
setWeapon (Weapon newWeapon ); // 将weapon更换成newWeapon
}
Weapon {
useWeapon ( ); // 抽象方法,具体代码由子类Sword,Horse,Spear,Bow等实现
}
Sword {
useWeapon ( ); // 在此实现具体的使用剑的代码
}
... // 省略Horse,Spear,Bow等
Weapon <--- Sword
<--- Horse
<--- Spear
<--- Bow
Character <--- Infantry
<--- Cavalry
<--- Spearman
<--- Archer
在方案三中,新增了一个Weapon类,它作为一个父类,Sword类等继承于它。
而Character类“拥有” [has a] Weapon类,而Character的子类Archer类、Infantry等,可以通过setWeapon (Weapon newWeapon)来设定武器,并通过呼叫useWeapon ( )来使用武器。
而当敌人靠近时,Archer类还可以在运行时 [runtime]通过setWeapon (Weapon newWeapon)改变自己的武器,从而进行近身战。
方案三相比于方案二,a) 增加了代码的可复用性,增加了代码的弹性,可以适用于更多的情况,例如,Spearman的可以在形成方阵时使用长矛,而在贴身肉搏中使用更为灵活的剑。在方案三中,只需要在调用setWeapon就可以实现了,而方案二则需要在Spearman中再写一遍useSpear( )方法。方案三还有一个好处 b) 因为Spear,Bow,Sword,Horse等类的实现与最终是哪一个具体的类并无关系 [也就是说,Sword类并不需要知道调用它的是Infantry类还是Spearman类]。这样,我们就可以修改Sword类等的代码,而不怕其余的代码也被改变。
没错,这就是策略模式!
相比于传统的继承,策略模式则采用了“组合” [composite]。策略模式中,Character的行为实际上并不是由自己自己实现的,而是委托给Weapon类的子类来实现的。而Weapon类的这些子类中,它们封装了具体的算法代码,并由统一的接口 [interface]——useWeapon ( )来调用。也由于这统一的接口,这些Weapon子类可以互用。
策略模式定义了算法族,分别封装起来,让它们可以相互替代,此模式让算法的变化独立于使用算法的客户。

浙公网安备 33010602011771号