策略模式:定义一系列的算法,单独封装并使它们可以相互替换。这一模式可以使算法独立于使用它的客户而变化。
策略模式
策略模式 Strategy[ˈstrætədʒi] Pattern
:定义一系列算法的方法,从概念上看,所有的这些算法完成的多是相同的工作,只是实现不同,他们可以使用相同的方法来调用算法,减少了类之间的耦合。
类图结构
结构解析
Strategy
抽象类,策略类,定义算法。
ConcreteStrategy
实现类,算法的具体实现。
Context
环境类,上下文,持有当前策略的引用。客户端可以通过上下文动态切换算法。
示例
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public abstract class Strategy { public abstract void algorithm(); }
public class ConcreteStrategy1 extends Strategy { @Override public void algorithm() { System.out.println("ConcreteStrategy1: Bubble sort."); } }
public class ConcreteStrategy2 extends Strategy { @Override public void algorithm() { System.out.println("ConcreteStrategy2: Insertion sort."); } }
public class Context { private Strategy strategy;
public void setStrategy(Strategy strategy){ this.strategy = strategy; }
public void algorithm(){ strategy.algorithm(); } }
public class TestStrategy { public static void main(String[] args) { Strategy strategy = new ConcreteStrategy1(); Context context = new Context(); context.setStrategy(strategy); context.algorithm();
strategy = new ConcreteStrategy2(); context.setStrategy(strategy); context.algorithm(); } }
ConcreteStrategy1: Bubble sort. ConcreteStrategy2: Insertion sort.
|
示例中,策略的选择由客户端来决定。
总结
策略模式简化了单元测试,每个算法是一个独立的类,可以通过自己的接口单独测试。策略模式同时体现了开闭原则:策略模式把一系列的可变算法进行封装,从而定义了良好的程序结构,在出现新的算法的时候,可以很容易的将新的算法实现加入到已有的系统中,而已有的实现不需要修改。
状态模式与策略模式的异同
- 相同点
策略模式也是为了消除或者简化条件语句,和责任链模式,状态模式很类似。所以类图结构上看起来几乎没有太大区别。
- 不同点
状态模式中各个状态子类都必须知道它的下一个状态是什么,并且逻辑判断都转移到子类中,客户端并不了解状态的转换逻辑。而策略模式中各个子类是并级的,可以相互替换,他们并不存在状态转换的关系。策略模式是针对单一并行算法的替换,客户端需要提前了解各算法差异,并在策略模式中指定一种算法。
策略模式和责任链模式的异同
- 相同点
在功能职责上都是用来简化或消除条件判断,客户端在使用时需要提前指定使用哪种策略,或者指定责任链模式中的下一个继任者。
- 不同点
两者在类图上有区别,责任链模式需要持有下一个责任人的引用,策略模式多一个上下文类,由上下文类来持有具体的策略。责任链模式存在级差,每个子类拥有不同的责任权限;而策略模式子类都是并级的,客户端在选用时只需要选择一种策略。
参考文档