组件协作模式之策略模式
动机
- 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂,而且有时候不支持使用的算法也是一个性能负担;
- 如何在运行时根据需要透明的改变算法的对象,将算法与对象本身解耦,从而避免上述问题?
Code Example
public enum TaxBase{
CN_Tax,
US_Tax,
DE_Tax,
FR_Tax // 更改 ...
}
public class SalesOrder{
TaxBase tax;
public void calculateTax(){
// ...
switch(tax){
case CN_Tax:
// ...
break;
case CN_Tax:
// ...
break;
case CN_Tax:
// ...
break;
// TODO:违反开闭原则
}
}
}
Refactoring
public abstract TaxStrategy{
public abstract double calculate(Context context);
}
public class USTax extends TaxStrategy{
@Override
public double calculate(Context context){
// ...
}
}
public class DETax extends TaxStrategy{
@Override
public double calculate(Context context){
// ...
}
}
public class CNTax extends TaxStrategy{
@Override
public double calculate(Context context){
// ...
}
}
// 扩展
public class FRTax extends TaxStrategy{
@Override
public double calculate(Context context){
// ...
}
}
public class SalesOrder{
TaxStrategy strategy;
public SalesOrder(TaxStrategy strategy){
this.strategy = strategy;
}
public double calculate(Context context){
// ...
Context context;
double val = strategy.calculate(context); // 多态调用
}
}
模式定义
定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换(变化),使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)。
结构
Context
- stategy
Strategy
- algorithmInterface()
ConcreteStrategyA
- algorithmInterface()
ConcreteStrategyB
- algorithmInterface()
ConcreteStrategyC
- algorithmInterface()
总结
- Stratrgy及其子类为组件提供了一系列可重用的算法,从而可以是的类型在运行时方便地根据需要在各个算法之间进行切换;
- 该模式提供了用条件判断语句(Bad smell of code)之外的另一种选择,消除的过程就是在解耦合;
- 如果Strategy对象没有实例变量,那么 各个上下文可以共享一个Strategy对象以节省对象开销。
变与不变
In Android or JDK
数组排序 -> sort strategy
public static <T> void sort(T[] array,int start,int end,Compatator<? super T> comparator ){
// ...
}
public interface Comparator<T>{
// 扩展点,提供子类实现
public int compare(T lhs,T rhs);
public boolean equals(Object object);
}