在平常的开发过程中经常遇到这样的情况:实现一个功能可以有多种算法或者策略,我们根据实际情况选择不同的算法或策略来完成该功能。例如,排序算法有插入排序,归并排序、冒泡排序。
定义:策略模式定义了一系列算法,并将每一个算法封装起来,而且它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
使用场景:
- 针对同一问题的多种处理方式,仅仅是具体行为有差别时。
- 需要安全地封装多种同一类型的操作时。
- 出现同一抽象类有多个子类,而又需要使用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));
}
}
复制代码
策略模式的优缺点
无论哪种模式都有其优缺点,当然我们每次在编写代码的时候需要考虑下其利弊。 策略模式的优点:
- 提供了快速替换继承关系的办法
- 减少代码中的if else等判断语句
- 实现的选择:策略模式可以提供不同的实现。
策略模式的缺点:
- 策略模式会造成很多策略类
- 通讯开销很大
- 必须自行知道所有的实现类有何不同,因此只有当行为类和角色行为相关的时候才需要使用策略模式。
note: 但行好事,莫问前程。