设计模式系列-策略模式

199 阅读4分钟

​ 策略模式是对算法的包装,是把使用算法的责任和算法本身分割开,委派给不同的对象管理。即对应某一个问题的一个处理方法簇,允许用户从该算法簇中挑选一个算法来解决某一问题,同时可以方便的更换算法或者增加新的算法,具体调用哪个算法由客户端来决定。

​ 通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。也就是说:准备一组算法,并将每一个算法封装起来,使得它们可以互换。

常规策略模式

策略模式当中主要涉及的有三个角色

  • 环境角色(Context):这个里面持有一个对Strategy的引用,供给客户端调用
  • 抽象策略角色(Strategy):这是一个抽象角色,包含了所有具体策略类的公共行为,通常由一个接口或者抽象类实现
  • 具体策略类(ConcreteStrategy):继承自抽象策略,在各自的类当中具体实现对应的公共行为

策略模式的关键点就在于策略类都需要继承自抽象策略类并且具体实现各自的算法

优点

  • 算法可以自由切换
  • 避免适用多重条件判断
  • 拓展性好,能够自由增删算法簇

缺点

  • 策略类会增多
  • 所有策略类都需要对外暴露

适用场景

  • 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
  • 一个系统需要动态地在几种算法中选择一种。
  • 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

拓展使用(工厂方法模式+策略模式)

工厂方法模式+策略模式

策略模式会将自己的内部算法类给暴露出去,然而通过结合工厂方法的模式的话,就能够对外隐藏内部算法类。

通用类图通常如图所示:

策略模式结合工厂模式

其中比较重要的几个类的代码实例如下:

  • 枚举类:枚举注册所有具体策略,负责对具体策略的映射
public class StrategyEnum{
    Strategy1("ConcreteStrategy1",new ConcreteStrategy1);
    Strategy2("ConcreteStrategy2",new ConcreteStrategy2);
    
    private String name;
    
    private Strategy strategy;
    
    StrategyEnum(String name,Strategy strategy){
        this.name=name;
        this.strategy=strategy;
    }
    
    public String getName(){
        return name;
    }
    
    public Strategy getStrategy(){
        return strategy;
    }
}
  • 工厂类:根据策略管理类的枚举项创建一个策略对象
public class StrategyFactory{
    private static Map<String,Startegy> strategies=new Concurrent	HashMap<String,Straregy>;
    
    public static Strategy getStrategy(String type){
        return strategies.get(type);
    }    
    
        static{
        //使用static语句块再开始时将算法类注册到Map内用于工厂实例化使用
        strategies.put(StrattegyEnum.Strategy1.getValue(), StrattegyEnum.Strategy1.getStrategy());
        strategies.put(StrattegyEnum.Strategy2.getValue(), StrattegyEnum.Strategy2.getStrategy());
    }
}
  • 上下文类
public class Context{
    private Strategy strategy;
    
    public Context(String type){
        this.strategy=StrategyFactory.getStrategy(type);
    }
    
    private void contextInterface(){
        strategy.algorithmInterface();
    }
}

模板模式+策略模式

在实际应用策略模式的过程中,经常会出现这样一种情况,就是发现这一系列算法的实现上存在公共功能,甚至这一系列算法的实现步骤都是一样的,只是在某些局部步骤上有所不同 ,这个时候,就需要对策略模式进行些许的变化使用了。

对于一系列算法的实现上存在公共功能的情况,策略模式可以有如下三种实现方式:

  • 在上下文当中实现公共功能,让所有具体的策略算法回调这些方法。
  • 把策略的接口改成抽象类,然后在里面实现具体算法的公共功能。
  • 给所有的策略算法定义一个抽象的父类,让这个父类去实现策略的接口,然后在这个父类里面去实现公共的功能。

其中第三种方式就是模板方法模式结合策略模式来实现。

主体结构是模板方法模式,局部采用策略模式。

通用类图通常如图所示:

策略模式结合模板模式

其中几个比较重要的类的实例代码如下

  • 抽象类:实现算法中的公共功能
public abstract class AbstractStrategy implements Strategy {
  public final void algorithmInterfac() {
      //第一步:实现公共功能
      公共功能代码
      //第二步:具体策略类实现具有差异的算法
      doAlgorithmInterface();
  }
                               
  protected abstract void doAlgorithmInterface();
}
  • 具体策略实现类:实现具体算法
public class ConcreteStrategy1 extends AbstractStrategy{
  //具体有差异性的算法
  public void doAlgorithmInterface(String msg) {   
      ...
  }
}

参考网址

blog.csdn.net/qq_20610631…

www.cnblogs.com/qlqwjy/p/11…

www.cnblogs.com/zhanglei93/…

www.jianshu.com/p/4049b0da6…