在平常的开发过程中经常遇到这样的情况:实现一个功能可以有多种算法或者策略,我们根据实际情况选择不同的算法或策略来完成该功能。例如,排序算法有插入排序,归并排序、冒泡排序。
定义:策略模式定义了一系列算法,并将每一个算法封装起来,而且它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
使用场景:
* 针对同一问题的多种处理方式,仅仅是具体行为有差别时。
* 需要安全地封装多种同一类型的操作时。
* 出现同一抽象类有多个子类,而又需要使用if-else来选择具体子类时。
UML类图

Context ----用来操作策略的上下文环境
Strategy ----策略的抽象
ConcreteStrategyA、ConcreteStrategyB ---- 具体的策略体现
简单实现
如果一个问题可以有多种解决方案时,最简单的方式就是通过if else根据情况选择需要的方案,但是这种方式耦合性太高,代码臃肿,难以维护。而且不遵循开闭原则,如果要新加一种方案还得去源代码修改。选择策略模式将各种方案分离开来,根据具体需求动态地选择不同的策略方案。
很简单一个问题,公交出行方案不同价格不同,公交车、地铁、出租车都有不同的价格计算。
1、策略的抽象
/**
* 抽象策略接口
*/
public interface CalculateStrategy {
/**
* 按距离计算价格
* @param km
* @return
*/
int calculatePrice(int km);
}
2、策略的具体实现
/**
* 具体的地铁策略实现
*/
public class SubwayStrategy implements CalculateStrategy {
@Override
public int calculatePrice(int km) {
System.out.println("选择地铁出行");
return 99;
}
}
/**
* 具体的公交车策略实现
*/
public class BusStrategy implements CalculateStrategy {
@Override
public int calculatePrice(int km) {
System.out.println("选择公交车出行");
return 9;
}
}
/**
* 具体的出租车策略实现
*/
public class TaxiStrategy implements CalculateStrategy {
@Override
public int calculatePrice(int km) {
System.out.println("选择出租车出行");
return 999;
}
}
3、操作策略的上下文Context
/**
* Context用来操作策略模式的上下文环境
*/
public class TranficCalculator {
CalculateStrategy mStrategy;
public void setStrategy(CalculateStrategy strategy) {
this.mStrategy = strategy;
}
public int calculatePrice(int km) {
return mStrategy.calculatePrice(km);
}
public static void main(String[] args) {
TranficCalculator calculator = new TranficCalculator();
//设置计算策略
calculator.setStrategy(new BusStrategy());
System.out.println(calculator.calculatePrice(100));
}
}
Android源码中的策略模式
时间插值器
抽象策略类 Interpolator
具体策略类
线性插值器:LinearInterpolator
减速插值器:DecelerateInterpolator
加速减速插值器:AccelerateDecelerateInterpolator
通过注入不同的插值器实现不同的动态效果。

总结
策略模式主要用来分离算法,在相同的行为抽象下有不同的具体实现策略。这个模式很好地演示了开闭原则,也就是定义抽象,注入不同的实现,从而达到很好的可扩展性。
优点:结构清晰明了、使用简单直观;耦合度相对较低,扩展方便;操作封装也更为彻底,数据更安全;
缺点:随着策略的增加,子类也会变得繁多。