策略模式

策略模式

定义

策略模式定义了一系列算法,并将每个算法封装起来,并且他们还能够相互替换。策略模式让算法独立于使用它的客户而独立变化。算法

使用场景

  • 针对同一类型的问题的多种处理方式,仅仅是具体行为有差异时
  • 须要安全的封装多种同一类型的操做时候
  • 出现同一抽象类有多个子类,而又须要用if-else或switch-case来选择具体子类时候

模式结构

  • Context 环境类设计模式

    环境类是使用算法的角色,它在实现某个方法时能够采起多种策略。在环境类中维护着对抽象策略类的引用。安全

  • Strategy 抽象策略类bash

    为所支持的算法声明抽象方法ide

  • ConcreteStrategy具体策略类工具

    具体实现了抽象策略类中定义的算法测试

需求分析

简单实现

以坐车出行为例子,来简单说明,假设选择的交通工具均以路程来计价,咱们须要计算最终需支付的金额。 小A要出去玩耍,走好出门,来了辆公交车,小A果断上去坐上了。优化

public class PriceCalculator {

  public static void main(String[] args) {
    PriceCalculator calculator = new PriceCalculator();
    System.out.println("坐16千米公交车票价:" + calculator.busPrice(16));
  }

  private int busPrice(int km) {
    int extraTotal = km - 10;
    //  超出10km部分  每5km需额外付1元 不足5km按照5km计算
    int extraFactor = extraTotal / 5;
    int fraction = extraTotal % 5;
    int price = 1 + extraFactor * 1;

    return fraction > 0 ? ++price : price;
  }
}

复制代码

这很简单嘛,咱们不假思索就能写出来了。 次日,小A又要外出了,这时公交车没有来,来了辆出租车,小A选择了坐出租车。 也很简单,只须要在PriceCalculator中添加一个出租车的方法就能够了ui

public class PriceCalculator {

  public static void main(String[] args) {
    PriceCalculator calculator = new PriceCalculator();
    System.out.println("坐16千米公交车票价:" + calculator.busPrice(16));
    System.out.println("坐16千米出租车票价:" + calculator.taxiPrice(16));
  }

  private int busPrice(int km) {
    int extraTotal = km - 10;
    //  超出10km部分  每5km需额外付1元 不足5km按照5km计算
    int extraFactor = extraTotal / 5;
    int fraction = extraTotal % 5;
    int price = 1 + extraFactor * 1;

    return fraction > 0 ? ++price : price;
  }

  private int taxiPrice(int km) {
    //10km内按起步价10元收费,超出部分每千米收费2元
    if (km < 10) {
      return 12;
    } else {
      return 16 + (km - 10) * 2;
    }
  }
}
复制代码

第三天,小A想换乘地铁了,一样的,往PriceCalculator中添加一个乘坐地铁的方法subPrice()便可,spa

System.out.println("坐地铁票价:" + calculator.subPrice(16));
      
  private int subPrice(int km) {
    int extraTotal = km - 6;
    int extraFactor = extraTotal / 5;
    if (km < 6) {
      return 3;
    } else {
      return 3 + extraFactor;
    }
  }
    
复制代码

等等,这样太麻烦了,每次调用一次出行方案,都得调用不一样的方法,那若是方法有5个10个,那不就太混乱了?没错,咱们能够用一个方法来统一管理出行方案,经过一个字段来判断选择哪一种出行方式啊。说干就干

public int calculatorPrice(int km, int type) {
    if (type == BUS) {
      return busPrice(km);
    } else if (type == TAIX) {
      return taxiPrice(km);
    } else if (type == SUBWAY) {
      return subPrice(km);
    }
    return -1;
  }
复制代码
System.out.println("坐16千米公交车票价:" + calculator.calculatorPrice(16, PriceCalculator.BUS));
    System.out.println("坐16千米出租车票价:" + calculator.calculatorPrice(16, PriceCalculator.TAIX));
    System.out.println("坐地铁票价:" + calculator.calculatorPrice(16, PriceCalculator.SUBWAY));
复制代码

如今调用起来比以前方便多了,但也使得calculatorPrice()逻辑变更比较混乱了,这时候还只有3种出行方案,若是须要添加一个新的出行方案,好比坐飞机、好比乘船、好比自驾等等,每多出一个方案就会让这里面的if else 变长,这会使得这个类愈来愈难以维护。更甚者,若是要取消一种出行方案,涉及到减小if else的时候,这时候就会很头疼,由于这种类通常都会做为公共类被调用,删除了颇有可能对其余地方形成影响。

那有什么方案优化一下吗?对于这种状况,因为咱们已经知道本身须要选择的出行方案,而又但愿能灵活切换所选方案的时候,就能够考虑策略模式了。

咱们先定义一个抽象接口,用来计算价格

public interface CalculateStrategy {

  /**
   * 根据距离计算价格
   *
   * @param km 千米 路程
   * @return 价格
   */
  int calculatePrice(int km);
}

复制代码

分别实现每种出行策略

public class BusStrategy implements CalculateStrategy {
  @Override public int calculatePrice(int km) {
    int extraTotal = km - 10;
    //  超出10km部分  每5km需额外付1元 不足5km按照5km计算
    int extraFactor = extraTotal / 5;
    int fraction = extraTotal % 5;
    int price = 1 + extraFactor * 1;

    return fraction > 0 ? ++price : price;
  }
}
复制代码
public class TaxiStrategy implements CalculateStrategy{
  @Override public int calculatePrice(int km) {
    if (km < 10) {
      return 12;
    } else {
      return 16 + (km - 10) * 2;
    }
  }
}
复制代码
public class SubwayStrategy implements CalculateStrategy {
  @Override public int calculatePrice(int km) {
    int extraTotal = km - 6;
    int extraFactor = extraTotal / 5;
    if (km < 6) {
      return 3;
    } else {
      return 3 + extraFactor;
    }
  }
}
复制代码

建立一个扮演Context角色的环境类

public class TrafficCalculator {

  CalculateStrategy mStrategy;

  public void setStrategy(CalculateStrategy strategy) {
    mStrategy = strategy;
  }

  public int calculatePrice(int km) {
   return mStrategy.calculatePrice(km);
  }
}

复制代码

实现测试类

public class Test {
  public static void main(String[] args) {
    TrafficCalculator calculator = new TrafficCalculator();
    calculator.setStrategy(new TaxiStrategy());
    calculator.calculatePrice(20);
  }
}

复制代码

这样咱们在选择不一样的出行方式时候,只须要经过calculator.setStrategy()方法指定对应的方式便可,其余地方的代码基本不须要变更,若是须要增长新的出行方案,也只须要新建一个具体策略类,而且实现CalculateStrategy接口便可。

思考

策略模式简化了逻辑、结构、下降了耦合性,加强了系统的可读性、稳定性与拓展性。合理的利用策略模式,能够有效的减小一部分if else带来的复杂性问题。

在一些简单状况下,用if else能办到的事情就不必过分设计了,不要滥用设计模式,这点好像也只能从经验中不断摸索了。

相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息