策略模式

1 鸭子问题

现在有种类繁多的鸭子(如野鸭、北京鸭、玩具鸭等),鸭子有各种行为,如叫、游泳等,现在要求显示鸭子的信息。传统方案是通过设计一个Duck父类,在Duck中定义了鸭子的行为(叫、游泳),然后让野鸭、玩具鸭等都继承Duck,覆盖相应的方法,这样设计会导致某些类需要覆盖基类的所有方法。

2 策略模式介绍

在策略模式(Strategy Pattern)中定义了算法族,分别封装,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。这种算法体现了几个原则:
1)把变化的代码从不变的代码中分离出来
2)针对接口编程而不是具体的类(定义了策略接口)
3)多用聚合/组合,少用继承(客户端通过组合方式使用策略)


策略模式类图

3 代码实现

为了简单,这里用Swim这个策略接口为例来实现策略模式。
首先有策略接口Swim,描述是否会游泳:

public interface Swim {
    void swim();
}

描述会游泳的策略实现类CanSwim:

public class CanSwim implements Swim {
    @Override
    public void swim() {
        System.out.println("会游泳");
    }
}

描述不会游泳的策略实现类CannotSwim:

public class CannotSwim implements Swim {
    @Override
    public void swim() {
        System.out.println("不会游泳");
    }
}

然后是鸭子的抽象基类Duck,对应到Context

public abstract class Duck {
    Swim swimBehavior;

    public abstract void display();

    public void quack() {
        System.out.println("鸭子在嘎嘎叫");
    }

    public void swim() {
        if (swimBehavior != null) {
            swimBehavior.swim();
        }
    }
}

野鸭会游泳,所以依赖CanSwim:

public class WildDuck extends Duck {
    public WildDuck() {
        swimBehavior = new CanSwim();
    }

    @Override
    public void display() {
        System.out.println("这是野鸭");
    }
}

玩具鸭不会游泳,所以依赖CannotSwim:

public class ToyDuck extends Duck {
    public ToyDuck() {
        swimBehavior = new CannotSwim();
    }

    @Override
    public void display() {
        System.out.println("这是玩具鸭");
    }
}

客户端调用:

public class Client {
    public static void main(String[] args) {
        Duck wildDuck = new WildDuck();
        wildDuck.display();
        wildDuck.swim();

        Duck toyDuck = new ToyDuck();
        toyDuck.display();
        toyDuck.swim();
    }
}

输出结果:

这是野鸭
会游泳
这是玩具鸭
不会游泳
策略模式实现鸭子问题的类图

4 策略模式的特点

1)策略模式的关键点在于分析项目中变化与不变的部分。
2)策略模式的核心思想是:多用聚合/组合,少用继承,用行为类组合比用行为类继承更有弹性。
3)策略模式体现了“对修改关闭,对扩展开放”的原则,客户端增加行为不需要修改原代码,只需要添加一种策略(或行为)即可,避免了使用多重转移语句(if-else...else-if)。
4)策略模式将算法封装在独立的Strategy类中,使得它可以独立于Context而改变,易于切换、理解和扩展。
5)每增加一个策略就要增加一个类,当策略过多时会导致类数目庞大。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容