
版权声明:本文为 冬夏 原创文章,可以随意转载,但请注明出处。
策略模式(Strategy):定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
相信我们很多人小时候都玩过一款叫做「 魂斗罗 」的游戏吧。在游戏里,人物可以获取不同的武器,从而打出不同类型、威力的子弹。那么,这在程序上是如何设计的呢?
首先想到的可能是可以用 if-else
或者 switch
的方式,列出所有可能的武器类型,比如下面的例子。
public class Soldier {
private int gunType = -1;
public static final int PISTOL = 1;
public static final int RIFLE = 2;
public void setGunType(int gunType) {
this.gunType = gunType;
}
public int getGunType() {
return gunType;
}
public void shoot(){
switch (gunType){
case PISTOL:
System.out.println("射出手枪子弹");
break;
case RIFLE:
System.out.println("射出步枪子弹");
break;
default:break;
}
}
}
public class Main {
public static void main(String[] args) {
// write your code here
Soldier soldier = new Soldier();
soldier.setGunType(Soldier.PISTOL);
soldier.shoot();
soldier.setGunType(Soldier.RIFLE);
soldier.shoot();
}
}
输出的结果为:
射出手枪子弹
射出步枪子弹
这种办法最大的缺点就是每次要新增或者要删除一种武器的时候,都要对士兵类进行修改,这就违背了「 对扩展开发,对修改关闭 」的设计原则。
其实遇到这种类型的问题,我们可以用「 策略模式 」解决。UML类图如下:

那么用策略模式解决上面的「 魂斗罗 」问题,代码如下:
public class Soldier {
private Gun gun;
public void setGun(Gun gun) {
this.gun = gun;
}
public Gun getGun() {
return gun;
}
public void shoot(){
if (gun != null){
gun.fire();
}
}
}
public interface Gun {
void fire();
}
public class Rifle implements Gun {
@Override
public void fire() {
System.out.println("射出步枪子弹");
}
}
public class Pistol implements Gun {
@Override
public void fire() {
System.out.println("射出手枪子弹");
}
}
public class Main {
public static void main(String[] args) {
// write your code here
Soldier soldier = new Soldier();
Gun pistol = new Pistol();
Gun rifle = new Rifle();
soldier.setGun(pistol);
soldier.shoot();
soldier.setGun(rifle);
soldier.shoot();
}
}
主要思路就是将 枪支 独立出来成为一个接口,每种类型的枪都实现这个接口,士兵 类持有枪支接口,并将具体的操作委托给枪支接口。
由此我们可以总结出「 策略模式 」一个很重要的特点就是:把变化的部分抽离出来。这实际上也是很多设计模式的指导思想。