1.简述

定义:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。策略模式让算法独立于它的使用者之外,可以自由修改。
21 策略模式 - 图1
来看看UML图,图中主要由三个部分组成
Strategy是使用接口还是抽象类,这个取决于一系列的策略中是否有共同属性或方法;如果没有,使用接口更加灵活方便,反之使用抽象类,抽象类中便可存放公共的属性以及方法。

2.简单实现

我们可以来一场说走就走的旅行,背上行囊,出发去丽江。这个时候我们就需要考虑出行方式和价格的问题了(贫穷)。我们可能需要知道飞机、火车、自驾的花费都是多少,再决定什么方式出行。我们先看看最简单的实现方式

原始代码

  1. public class LetGo {
  2. public static final String MODE_AIRPLAN = "airPlan";
  3. public static final String MODE_TRAVEL = "travel";
  4. public static final String MODE_CAR = "car";
  5. public void printSpend() {
  6. Log.i(TAG, "出行花费: ¥" + getSpend(MODE_AIRPLAN));
  7. }
  8. private int needSpend(String mode) {
  9. switch (mode) {
  10. case MODE_AIRPLAN:
  11. return 1400;
  12. case MODE_TRAVEL:
  13. return 500;
  14. case MODE_CAR:
  15. return 2400;
  16. //异常值
  17. default:
  18. return -1;
  19. }
  20. }
  21. }

如同前文所说的,当需要添加可选的出行方案时,我们不得不去修改needSpend()函数中的switch case来达到目的;然而这样并不利于后期的维护。接下来,试着使用策略模式来使实现这个简单的出行案例。

策略模式代码

既然,出行方案是可选的策略,就可以先抽象出一个出行策略的接口,包含needSpend()方法,返回出行花费的方法

  1. public interface ITravelStrategy {
  2. public int needSpend();
  3. }

接着,实现各种具体出行方案需要的类,在needSpend()方法返回该出行方案所需的费用。

  1. /** 飞机出行 */
  2. public class AirPlanStrategy implements ITravelStrategy {
  3. @Override
  4. public int needSpend() {
  5. return 1400;
  6. }
  7. }
  8. /** 火车出行 */
  9. public class TrainStrategy implements ITravelStrategy {
  10. @Override
  11. public int needSpend() {
  12. return 500;
  13. }
  14. }
  15. /** 自驾出行 */
  16. public class CarStrategy implements ITravelStrategy {
  17. @Override
  18. public int needSpend() {
  19. return 2400;
  20. }
  21. }

这里,我们需要的策略就已经完成了,就等着我们选一种方案,看看所需要的花费。我们创建一个类,和Strategy组合使用来获取各种出行方的花费,并在printSpend()方法中打印出行所需的花费。

  1. public class LetGo {
  2. ITravelStrategy mTravelStrategy;
  3. public LetGo(@NonNull ITravelStrategy strategy){
  4. mTravelStrategy = strategy;
  5. }
  6. public void printSpend(){
  7. Log.i(TAG, "出行花费: ¥" + mTravelStrategy.needSpend());
  8. }
  9. }

以上的代码就可以完成自驾游花费的输出,策略模式我们就完成了。现在代码是不是比之前使用switch case实现的代码结构更加清晰、简洁。如果需要知道更多的出行方式的花费,只需要实现再实现ITravelStrategy接口,替换掉传入LetGo构造器的参数即可。

  1. //输出自驾游花费
  2. LetGo letGo = new LetGo(new CarStrategy()):
  3. letGo.printSpend();

3.总结
策略模式,其实可以简单地理解成,将过多的switch case中case的代码封装成一个个具有共性的对象,需要什么我们就直接使用什么;对于这种共性的实现就利用interface或者是抽象类来实现。这从对代码的封装以及解耦的角度来理解,可能会更加容易理解。
使用场景
优点
缺点