策略模式

策略模式(Strategy)

  • 定义一系列算法,把他们一个一个封装起来,并且使它们可互相替换(变化).该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展 ,子类化)
  • 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将算法都硬编码到对象中,将会使对象变的异常复杂;而且有时候支持不使用的算法也是一种性能负担
  • 策略模式要解决的问题:
    • 如何在运行时根据需要透明地 更改对象的算法?
    • 将算法与对象本身解耦,从而避免上述问题?

      代码例子

      常见做法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      //枚举类型来区分不同算法类别
      public enum TaxBase {
      CN_Tax,
      US_Tax,
      DE_Tax
      }

      public class SalesOrder {

      TaxBase tax;

      public void calculateTax(){
      //使用switch来判断不同类别的算法,并进行调用
      switch(tax){
      case CN_Tax:
      //算法一
      //.....
      break;
      case US_Tax:
      //算法二
      //.....
      break;
      case DE_Tax:
      //算法三
      //.....
      break;
      }
      }

      }

策略模式改写方案

  • Strategy及其子类为组件提供了一系列 可重用的算法 ,从而可以使类型在运行时方便地根据需要在各个算法之间进行切换
  • Strategy模式 提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦. 含有许多条件判断语句的代码通常都有Strategy模式.
  • 如果Strategy模式对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象的开销.
  • PS: 对于后续不需要改变算法的需求,没必要使用策略模式,比如上述代码中枚举对象不会改变,可以保持判断处理逻辑.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    abstract class TaxStraregy {

    public abstract double Calculate(Context context);

    }

    public class CNTax extends TaxStraregy {
    @override
    public double Calculate(Context context){
    //算法一
    //.....
    }
    }

    public class USTax extends TaxStraregy {
    @override
    public double Calculate(Context context){
    //算法二
    //.....
    }
    }

    public class DETax extends TaxStraregy {
    @override
    public double Calculate(Context context){
    //算法三
    //.....
    }
    }

    public class SaleOrder {
    TaxStraregy Strategy;

    public SaleOrder(TaxStraregy Strategy){
    this.Strategy = Strategy;
    }

    public double CalculateTax(){
    Context context;

    //多态调用
    double result = Strategy.Calculate(context);
    }

    }