概述
策略模式(Strategy)是一种行为型模式,
好处是我们可以动态的改变对象的行为.针对一组算法或者策略,我们可以将其抽象出来,提供一个统一的接口,不同的算法或者策略有不同的实现类,
通过注入不同的对象实现策略的动态替换,提高扩展性和维护性.
定义
策略模式定义了一系列算法,并将每一个算法封装起来,使得他们可以相互替换,策略模式让算法独立于使用它的客户端,在不影响到客户端的情况下发生变化.
使用场景
- 针对同一类型问题的多种处理方式,仅仅是具体行为有差异时.
- 需要安全的封装多种同一类型的操作时.
- 出现同一抽象类有多个子类,而又需要根据不同情况来选择具体的子类时.
UML 类图
策略模式相当于算法的封装,将算法本身和其实现功能分离开来.
策略模式角色介绍:
- Context : 操作策略的上下文环境,持有
Strategy
引用 - Strategy: 抽象策略角色,通常是一个接口或抽象类,提供具体策略所需接口.
- ConcreteStrategy : 具体策略角色,包装了一系列算法或行为.
通常一个问题有多种解决办法时,可以使用if-else 或者 switch-case.
这种方法很简单,但是问题也非常多,耦合性高,代码臃肿,不能适应变化.而使用策略模式就很好的避免了这个问题,符合开闭原则和单一原则.
实例
普通模式
首先来一个没有使用策略模式之前的代码
private static final int BUS = 1;
private static final int SUBWAY = 2;
public static void main(String[] args) {
Nomal nomal = new Nomal();
System.out.println("BUS--->" + nomal.calculate(3, BUS));
System.out.println("SUBWAY--->" + nomal.calculate(3, SUBWAY));
}
// 模拟公交车计费
private int bus(int km) {
return 10 * km;
}
//模拟火车计费
private int subWay(int km) {
return 5 * km;
}
int calculate(int km, int type) {
if (type == BUS) {
return bus(km);
} else {
return subWay(km);
}
}
此时,如果我们想增加一种类型,就需要更改源代码了.
策略模式
接下来使用策略模式实现的代码
- 首先定义策略接口
public interface Calculate {
int calculate(int km);
}
- 具体策略
//公交车策略
public class BusCal implements Calculate {
@Override public int calculate(int km) {
return 10*km;
}
}
//火车策略
public class SubCal implements Calculate {
@Override public int calculate(int km) {
return 5*km;
}
}
- context角色
public class TranficCal {
private Calculate mCalculate;
public void setCalculate(Calculate calculate) {
mCalculate = calculate;
}
public int calculate(int km){
return mCalculate.calculate(km);
}
public static void main(String[] args){
TranficCal tranficCal = new TranficCal();
tranficCal.setCalculate(new BusCal());
System.out.print("BUS -- >"+ tranficCal.calculate(3));
}
}
这时候,如果我们想要新增一种出租车的策略就非常的简单,只需要实现策略接口即可,且不用修改原来的代码.
策略模式的特点
- 封装具体的策略和算法,而在什么情况下使用什么算法是由客户端决定的.
- 其重心并不是如何实现算法,而是如何组织和调用这些算法.
- 策略模式中各个算法的地位是平等的,相互独立的,因此可以相互替换.
- 策略中虽然有一组算法,但是在某一时刻,只能使用其中一个