1.简述
定义:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。策略模式让算法独立于它的使用者之外,可以自由修改。
来看看UML图,图中主要由三个部分组成
Strategy是使用接口还是抽象类,这个取决于一系列的策略中是否有共同属性或方法;如果没有,使用接口更加灵活方便,反之使用抽象类,抽象类中便可存放公共的属性以及方法。
2.简单实现
我们可以来一场说走就走的旅行,背上行囊,出发去丽江。这个时候我们就需要考虑出行方式和价格的问题了(贫穷)。我们可能需要知道飞机、火车、自驾的花费都是多少,再决定什么方式出行。我们先看看最简单的实现方式
原始代码
public class LetGo {public static final String MODE_AIRPLAN = "airPlan";public static final String MODE_TRAVEL = "travel";public static final String MODE_CAR = "car";public void printSpend() {Log.i(TAG, "出行花费: ¥" + getSpend(MODE_AIRPLAN));}private int needSpend(String mode) {switch (mode) {case MODE_AIRPLAN:return 1400;case MODE_TRAVEL:return 500;case MODE_CAR:return 2400;//异常值default:return -1;}}}
如同前文所说的,当需要添加可选的出行方案时,我们不得不去修改needSpend()函数中的switch case来达到目的;然而这样并不利于后期的维护。接下来,试着使用策略模式来使实现这个简单的出行案例。
策略模式代码
既然,出行方案是可选的策略,就可以先抽象出一个出行策略的接口,包含needSpend()方法,返回出行花费的方法
public interface ITravelStrategy {public int needSpend();}
接着,实现各种具体出行方案需要的类,在needSpend()方法返回该出行方案所需的费用。
/** 飞机出行 */public class AirPlanStrategy implements ITravelStrategy {@Overridepublic int needSpend() {return 1400;}}/** 火车出行 */public class TrainStrategy implements ITravelStrategy {@Overridepublic int needSpend() {return 500;}}/** 自驾出行 */public class CarStrategy implements ITravelStrategy {@Overridepublic int needSpend() {return 2400;}}
这里,我们需要的策略就已经完成了,就等着我们选一种方案,看看所需要的花费。我们创建一个类,和Strategy组合使用来获取各种出行方的花费,并在printSpend()方法中打印出行所需的花费。
public class LetGo {ITravelStrategy mTravelStrategy;public LetGo(@NonNull ITravelStrategy strategy){mTravelStrategy = strategy;}public void printSpend(){Log.i(TAG, "出行花费: ¥" + mTravelStrategy.needSpend());}}
以上的代码就可以完成自驾游花费的输出,策略模式我们就完成了。现在代码是不是比之前使用switch case实现的代码结构更加清晰、简洁。如果需要知道更多的出行方式的花费,只需要实现再实现ITravelStrategy接口,替换掉传入LetGo构造器的参数即可。
//输出自驾游花费LetGo letGo = new LetGo(new CarStrategy()):letGo.printSpend();
3.总结
策略模式,其实可以简单地理解成,将过多的switch case中case的代码封装成一个个具有共性的对象,需要什么我们就直接使用什么;对于这种共性的实现就利用interface或者是抽象类来实现。这从对代码的封装以及解耦的角度来理解,可能会更加容易理解。
使用场景
优点
缺点
