策略模式的理解和实例

是什么?作用?

策略模式的思想是定义一些算法族,分别封装起来,让他们可以相互替换,此模式让算法的变化独立于使用算法的客户

策略模式的适用场景:

  • 当一个系统中有许多类,它们之间的区别仅在于它们的行为,希望动态地让一个对象在许多行为中选择一种行为时;
  • 当一个系统需要动态地在几种算法中选择一种时;
  • 当一个对象有很多的行为,不想使用多重的条件选择语句来选择使用哪个行为时。

使用实例

  • 场景:鸭子分为绿头鸭和模型鸭子,以后还能有其他鸭子,绿头鸭可以呱呱叫,也可以用翅膀飞,模型鸭子可以呱呱叫,但是不能飞
  1. 定义飞的接口行为 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    /**
    * 飞的接口类
    */
    public interface FlyBehavior {

    void fly();
    }

    // ============================
    /**
    * 用翅膀飞 - 实现类
    */
    public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
    System.out.println("I'm flying");
    }
    }

    // =========================

    /**
    * 不会飞 - 实现类
    */
    public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
    System.out.println("I can't fly");
    }
    }
  2. 定义叫的接口行为

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    /**
    * 叫的接口类
    */
    public interface QuackBehavior {

    void quack();
    }

    // =======================
    /**
    * 咕咕叫
    */
    public class MuteQuack implements QuackBehavior {
    @Override
    public void quack() {
    System.out.println("咕咕叫");
    }
    }

    // =======================

    /**
    * 嘎嘎叫
    */
    public class Squeak implements QuackBehavior {
    @Override
    public void quack() {
    System.out.println("嘎嘎叫");
    }
    }
  3. 编写鸭子类, 注意这里用的是组合

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    /**
    * 鸭子类 基类, 注: 这里可以写给set行为的方法,方便动态设置行为
    */
    public abstract class Duck {

    private FlyBehavior flyBehavior;
    private QuackBehavior quackBehavior;

    public Duck() { }

    // 执行飞的动作
    public void performFly() {
    flyBehavior.fly();
    }

    // 执行叫的动作
    public void performQuack() {
    quackBehavior.quack();
    }
    }
    /**
    * 绿头野鸭类 注意点: 就在鸭子的行为在这个时候赋值给鸭子, 想换别的行为随便换
    */
    public class MallardDuck extends Duck{

    public MallardDuck() {
    this.flyBehavior = new FlyWithWings();
    this.quackBehavior = new MuteQuack();
    }
    }
  4. 测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
    * 小鸭子测试类
    */
    public class MiniDuckSimulator {

    public static void main(String[] args) {
    Duck mallard = new MallardDuck();
    mallard.performFly();
    mallard.performQuack();
    }
    }

总结

  1. 如果是以前我很可能有鸭子抽象类来定义飞的行为,子类重写飞的行为,当忽然添加另外一种鸭子,它有特殊的行飞的行为(带火箭喷射器的翅膀),这时候又得重写这个行为,不管什么鸭子,我都得重写他的飞的行为;

  2. 如果用了策略模式,只需要要编写这个特殊飞的行为,然后在这只鸭身上赋上这种行为就行了,其他已经编写的代码一点都没有收到影响,牛批