策略模式
策略是指根据不同的情况,选择不同的策略。要求策略根据情况的不同进行动态的改变(有点诸葛亮的锦囊妙计一样的感觉)。
以OO(面向对象)的思维来看,我们可以把不同的情况视为不同的子类,不同的策略看做类的不同行为或算法。其实策略模式就是实现的这一思想,在接下来的类设计中就可以清楚的看到。
1 概念
策略模式可以使得一个类的行为或其算法可以在运行时更改。
2 动机
在有多种算法相似的情况下,使用if…else所带来的复杂和难以维护。
3 结构
根据文章开始对策略的描述“策略是指根据不同的情况,选择不同的策略”,就可以发现有两大实体,一个是情况,二是策略。所以可以大体认为结构是由**“情况”**与“**策略”**这两个部分构成。
4 参与者
我们通常将“策略”写成一个接口,具体的策略(即算法)便是接口的实现。(面向接口编程)
在《设计模式:可服用面向对象软件的基础》一书中,“情况”对应的便是Context(上下文)。而Context持有对接口的引用便可动态的选择策略的多个实现。
所以我们可以得到三个参与者。
- Strategy(策略)
- 定义所有支持的算法的公共接口。Context使用这个接口来调用某一个ConcreteStrategy定义的算法。
- ConcreteStrategy(具体策略)
- 以Strategy接口实现具体算法。
- Context(上下文)
- 持有对Strategy引用。
5 实例
游戏里的角色(国王、女王、骑士)可以选择不同的武器(剑、匕首、弓箭)进行战斗。
使用策略模式来表达,UML图则如下:
使用武器攻击,对于角色来说是一个共同的行为,但又需要具备灵活性。所以不能写死在每个角色具体的实现类中,需要将其抽取出来作为接口(WeaponBehavior),并将算法封装到不同的接口实现类的方法中去。
创建一个Character(角色)类作为三种角色的基类,在基类中对策略接口进行引用。
可在子类的构造方法中初始化weapon对象引用的具体子类,或通过set方法(即setWeapon()方法)进行改变。
6 代码
对应以上UML图的设计,贴部分关键代码:Character类、一个Character子类、策略接口、一个策略接口实现类、main函数
【Character类】
public abstract class Character {
//引用接口
//因为要被子类继承,所以使用protected
protected WeaponBehavior weapon;
public void fight() {
//调用接口方法
weapon.userWeapon();
}
public void setWeapon(WeaponBehavior weapon) {
this.weapon = weapon;
}
public abstract void say();
}
【Character子类——King类】
public class King extends Character{
public King(){
//构造函数中配置接口实现类
this.weapon = new Sword();
}
@Override
public void say() {
System.out.println("我是国王!");
}
}
【策略接口】
public interface WeaponBehavior {
public void userWeapon();
}
【策略接口实现类】
public class Sword implements WeaponBehavior {
@Override
public void userWeapon() {
System.out.println("使用宝剑挥砍!");
}
}
【main函数】
public class TestMain {
public static void main(String[] args) {
Character king = new King();
king.say();
king.fight();
king.setWeapon(new Knife());
king.fight();
}
}