设计模式 - 策略模式(Strategy)

定义

定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。策略模式使得算法可以独立于使用它的客户而变化。

类型

对象行为模式

适用性

以下情况适用策略模式:

  1. 许多相关的类仅仅是行为有异,策略模式提供了一种用多个行为中的一个行为来配置一个类的方法;
  2. 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间 / 时间权衡的算法。当这些变体实现为一个算法的类层次时 ,可以使用策略模式;
  3. 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构;
  4. 一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。

结构

策略模式结构

参与者

抽象策略(Strategy): 定义所支持的算法的公共接口,Context使用此接口来调用某ConcreteStrategy定义的算法;

具体策略(ConcreteStrategy): 以Strategy接口实现某具体算法

上下文(Context): 用一个ConcreteStrategy对象来配置,同时维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。

优缺点

优点

(1)由于具体策略实现同一个策略接口,不同策略可以自由的切换;

(2)避免使用多重条件判断,如果有多重策略,那么每个策略只需实现自己的方法,至于采用何种策略,可以由调用者决定;

(3)扩展性良好,在现有的系统中加入新的策略,只需实现策略接口。

缺点

(1)策略类数量增多,每个策略都是一个类,复用的可能性很小;

(2)所有的策略都需要对外暴露,客户端必须知道有哪些策略,然后才能知道采用哪种策略。

策略模式实现

抽象策略(Strategy)

public interface SortStrategy {
    int[] sort(int[] nums);
}

具体策略(ConcreteStrategy)

public class MergesortStrategy implements SortStrategy {
    @Override
    public int[] sort(int[] nums) {
        System.out.println("MergesortStrategy.sort...");
        return new int[0];
    }
}

public class QuicksortStrategy implements SortStrategy {
    @Override
    public int[] sort(int[] nums) {
        System.out.println("QuicksortStrategy.sort...");
        return new int[0];
    }
}

public class ShellsortStrategy implements SortStrategy{
    @Override
    public int[] sort(int[] nums) {
        System.out.println("ShellsortStrategy.sort...");
        return new int[0];
    }
}

上下文(Context)

public class Context {
    private SortStrategy strategy;

    public Context(SortStrategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(SortStrategy strategy) {
        this.strategy = strategy;
    }

    public int[] sort(int[] nums) {
        return this.strategy.sort(nums);
    }
}

客户端(Client)

public class Client {

    public static void main(String[] args) {
        new Client().test();
    }

    private void test() {
        int[] nums = {1, 5, 8, 2, 4, 3};

        Context context = new Context(new QuicksortStrategy());
        context.sort(nums);

        context.setStrategy(new MergesortStrategy());
        context.sort(nums);

        context.setStrategy(new ShellsortStrategy());
        context.sort(nums);
    }
}

参考代码

https://github.com/xueyufish/design-pattern-java/tree/master/strategy