策略模式(Strategy Pattern):定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。
既然标题是 “趣玩” ,那么就要体现 “趣” 字和 “玩” 字。假设现在你是个开发游戏的小白,主创团队给了你一个项目,要求你开发一个玩家solo类型的游戏。大致思路如下:玩家每一回合可以选择一个角色(角色包括king国王,knight骑士,queen女王,troll穴居巨怪)进行游戏,游戏过程中,玩家可以切换武器(axe斧头,bowandarrow弓箭,sword宝剑,knief匕首)来适应不同的战斗。那么作为一个小白,我首先想到的就是,为每个角色,每个武器建一个类,在类里面实现不同的方法,角色类里拥有所有的武器属性,你可以通过相应的方法来使用这些武器进行攻击。
代码实现如下(角色类只实现一个knight类):
//武器之斧头类
package pattern.strategy;
public class AxeWeapon {
public void fight() {
System.out.println("使用 斧头 攻击");
}
}
//武器之弓箭类
package pattern.strategy;
public class BowAndArrowWeapon {
public void fight() {
System.out.println("使用 弓箭 攻击");
}
}
//武器之匕首类
package pattern.strategy;
public class KnifeWeapon {
public void fight() {
System.out.println("使用 匕首 攻击");
}
}
//武器之宝剑类
package pattern.strategy;
public class SwordWeapon {
public void fight() {
System.out.println("使用 宝剑 攻击");
}
}
//这个是演示的一个角色,简单的骑士类
package pattern.strategy;
public class EasyKnight {
private AxeWeapon axe = new AxeWeapon();
private BowAndArrowWeapon arrow = new BowAndArrowWeapon();
private KnifeWeapon knife = new KnifeWeapon();
private SwordWeapon sword = new SwordWeapon();
public void useAxe() {
axe.fight();
}
public void useArrow() {
arrow.fight();
}
public void useKnife() {
knife.fight();
}
public void useSword() {
sword.fight();
}
public static void main(String[] args) {
EasyKnight easyKnight = new EasyKnight();
easyKnight.useArrow();
}
}
可以看到代码耦合度较高,不管你使不使用某个武器,你都必须有相应的武器属性和武器方法,而且后期要增加武器必须使用硬编程的方式,在相应的角色里面增加武器。那么该怎么样才能实现武器的动态添加。
来思考策略模式的定义,定义了“算法族”,何为“算法族”,就是一系列算法,它们之间是有联系的。比如上面各种不同的武器,就是典型的算法族,都可以作为角色的武器。
现在这样想,如果我每次只有在一个角色需要某个武器时才动态的给它,那么是不是以后增加武器,就不用在角色类里面编程了,只需要动态添加就可以。既然是动态添加就肯定涉及到setXXX(),涉及到setXXX(),肯定就要在角色类里面定义一个武器属性,这个属性必须是所有武器的超类,或者接口。那么我们可以大致得出这样一个UML图。
代码实现如下:
//武器接口
package pattern.strategy;
public interface WeaponBehavior {
public void useWeapon();
}
//斧头类实现了武器接口
package pattern.strategy;
public class AxeWeapon implements WeaponBehavior{
@Override
public void useWeapon() {
System.out.println("使用 斧头 攻击");
}
}
//弓箭类实现了武器接口
package pattern.strategy;
public class BowAndArrowWeapon implements WeaponBehavior{
@Override
public void useWeapon() {
System.out.println("使用 弓箭 攻击");
}
}
//匕首类实现了武器接口
package pattern.strategy;
public class KnifeWeapon implements WeaponBehavior{
@Override
public void useWeapon() {
System.out.println("使用 匕首 攻击");
}
}
//宝剑类实现了武器接口
package pattern.strategy;
public class SwordWeapon implements WeaponBehavior{
@Override
public void useWeapon() {
System.out.println("使用 宝剑 攻击");
}
}
//抽象的角色类
package pattern.strategy;
public abstract class Character {
private WeaponBehavior weapon;
public void fight() {
weapon.useWeapon();
}
public void setWeapon(WeaponBehavior weapon2) {
// TODO Auto-generated method stub
this.weapon = weapon2;
}
}
//King类实现了角色类
package pattern.strategy;
public class DiffKing extends Character{
public static void main(String[] args) {
Character king = new DiffKing();
WeaponBehavior weapon = new KnifeWeapon();
king.setWeapon(weapon);
weapon.useWeapon();
}
}
可以看到当使用这个方案时,就可以实现武器的动态切换,通过setWeapon()方法。因为角色类本身有一个WeaponBehavior类型的属性,利用java的多态,该属性可以拥有不同的武器属性的状态。在下次你要增加武器来增加游戏的可玩性时,你就可以写一个武器类实现WeaponBehavior接口,然后通过setWeapon()方法把武器给角色类,这样就可以实现武器的动态切换了。