策略模式

简介

Joe上班的公司设计一个非常成功的游戏,游戏中国王和女王可以使用武器进行攻击

内容
  1. 此系统内部设计使用了标准的oo技术,设计了一个角色的超类,并让国王和女王继承此超类。
  2. 去年,公司的竞争压力加剧,老板决定引入会飞的天使。那么问题来了,如果使用继承的话,国王和女王是无法飞行的。所以通过直接继承父类的方式是不可取的。
  3. 利用接口如何?实现不同的接口会导致很多相同的行为无法重复使用,例如大家的武器都是弓箭,那每个角色都要重新实现一遍。
  4. 如果老板要求再增加一个骑马的骑士,那又要重新检查一遍之前的代码。那么是否有一种模式让我们以对既有代码影响最小的方式来修改软件。是的策略模式正好可以满足此想法。
  5. 策略模式:定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
  6. 定义一个抽象类,为行为接口类型声明两个引用变量,所有角色子类都继承它们。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public abstract class Character {
    public Character() {
    }
    //使用的武器
    WeaponBehavior weapon;
    //移动的方式
    MoveBehavior move;
    public void performFlght(){
    weapon.useWeapon();
    }
    public void performMove(){
    move.move();
    }
    //外观
    public abstract void display();

    public void wearArmor(){
    //每个角色需要穿上盔甲
    System.out.println("Every Character should Wear armor.");
    }
    }
  7. 武器方式

    1
    2
    3
    public interface MoveBehavior {
    void move();
    }

使用匕首刺杀

1
2
3
4
5
6
public class KnifeBehavior implements WeaponBehavior {
@Override
public void useWeapon() {
System.out.println("使用匕首刺杀");
}
}

使用弓箭射击

1
2
3
4
5
6
public class BowAndArrowBehavior implements WeaponBehavior {
@Override
public void useWeapon() {
System.out.println("使用弓箭射击");
}
}

使用宝剑挥舞

1
2
3
4
5
6
public class SwordBehavior implements WeaponBehavior {
@Override
public void useWeapon() {
System.out.println("使用宝剑挥舞");
}
}

  1. 相应的移动方式也需要实现MoveBehavior接口,例如飞行,骑马,坐马车等方式。
  2. 这时我们创建一个国王就很简单了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class King extends Character {

    public King(){
    //用宝剑
    weapon = new SwordBehavior();
    //坐马车
    move = new CarriageBehavior();
    }

    @Override
    public void display() {
    System.out.println("I am a king!");
    }
    }
  3. 测试类;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class GameSimulator {
    public static void main(String[] args) {
    Character kind = new King();
    kind.display();
    kind.performFlght();
    kind.performMove();
    kind.setWeapon(new BowAndArrowBehavior());
    kind.performFlght();
    }
    }

除了使用构造器的方式创建行为,还可以通过set方式,对行为进行动态切换。

总结

设计原则:多用组合,少用继承。