定义
定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。策略模式使得算法可以独立于使用它的客户而变化。
类型
对象行为模式
适用性
以下情况适用策略模式:
- 许多相关的类仅仅是行为有异,策略模式提供了一种用多个行为中的一个行为来配置一个类的方法;
- 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间 / 时间权衡的算法。当这些变体实现为一个算法的类层次时 ,可以使用策略模式;
- 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构;
- 一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的
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