策略模式

1.定义

策略模式(Strategy)作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法.

维基百科-策略模式

2.认识策略模式

  1. 策略模式的功能

策略模式的功能是把具体的算法实现,从具体的业务处理里面独立出来,实现成为单独的算法类,从而形成一系列的算法,并让这些算法可以相互替换.

策略模式的重心不是如何来实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活、具有更好的维护性和扩展性.

  1. 策略模式和if-else语句

每个策略算法具体实现的功能,就是原来if-else结构中的具体实现.其实多个if-else语句表达的就是一个平等的功能结构,你要么执行if,要不你就执行else,或者是elseif,这个时候,if块里面的实现和else块里面的实现从运行地位上来讲就是平等的.

而策略模式就是把各个平等的具体实现封装到单独的策略实现类了,然后通过上下文来与具体的策略类进行交互.

因此多个if-else语句可以考虑使用策略模式.

  1. 算法的平等性

策略模式一个很大的特点就是各个策略算法的平等性.对于一系列具体的策略算法,大家的地位是完全一样的,正是因为这个平等性,才能实现算法之间可以相互替换.

所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的.

所以可以这样描述一系列策略算法: 策略算法是相同行为的不同实现.

  1. 谁来选择具体的策略算法

在策略模式中,可以在两个地方来进行具体策略的选择.

一个是在客户端,在使用上下文的时候,由客户端来选择具体的策略算法,然后把这个策略算法设置给上下文.

还有一个是客户端不管,由上下文来选择具体的策略算法.

  1. Strategy的实现方式

Strategy都是使用接口来定义的,这也是常见的实现方式.但是如果多个算法具有公共功能的话,可以把Strategy实现成为抽象类,然后把多个算法的公共功能实现到Strategy里面.

  1. 运行时策略的唯一性

运行期间,策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态的在不同的策略实现中切换,但是同时只能使用一个.

  1. 增加新的策略

策略模式中切换算法是很方便的,但是增加一个新的算法会怎样呢?

其实很简单,策略模式可以让你很灵活的扩展新的算法.具体的做法是: 先写一个策略算法类来实现新的要求,然后在客户端使用的时候指定使用新的策略算法类就可以了.

3.实现

策略模式(Strategy)

  • 环境(Context)角色
  • 抽象策略(Strategy)角色
  • 具体策略(Concrete Strategy)角色

UML

环境(Context)角色: 对策略进行二次封装,目的是避免高层模块对策略的直接调用

/**
 * 环境(Context)角色
 */
public class Context {

    private Strategy strategy;
    // Constructor
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void execute() {
        this.strategy.execute();
    }

}

抽象策略(Strategy)角色: 提供具体策略类所需的统一接口

/**
 * 抽象策略(Strategy)角色
 */
public interface Strategy {

    void execute();
}

具体策略(Concrete Strategy)角色: 包装了相关的算法或行为

/**
 * 具体策略(Concrete Strategy)角色
 */
// Implements the algorithm using the strategy interface
public class FirstStrategy implements Strategy {

    public void execute() {
        System.out.println("Called FirstStrategy.execute()");
    }
}

/**
 * 具体策略(Concrete Strategy)角色
 */
// Implements the algorithm using the strategy interface
public class SecondStrategy implements Strategy {

    public void execute() {
        System.out.println("Called SecondStrategy.execute()");
    }
}

测试客户端

/**
 * 测试客户端
 */
public class StrategyClient {

    public static void main(String[] args) {
        Context context = new Context(new FirstStrategy());
        context.execute();

        context = new Context(new SecondStrategy());
        context.execute();

        // stdout
        // Called FirstStrategy.execute()
        // Called SecondStrategy.execute()
    }
}

4.总结

优缺点

  • 定义一系列算法
  • 避免多重条件语句
  • 更好的扩展性
  • 客户必须了解每种策略的不同
  • 增加了对象数目
  • 只适合扁平的算法结构

对设计原则的体现 从设计原则上来看,策略模式很好的体现了开-闭原则.策略模式通过把一系列可变的算法进行封装,并定义出合理的使用结构,使得在系统出现新算法的时候,能很容易的把新的算法加入到已有的系统中,而已有的实现不需要做任何修改.

从设计原则上来看,策略模式还很好的体现了历史替换原则.策略模式是一个扁平结构,一系列的实现算法其实是兄弟关系,都是实现同一个接口或者继承的同一个父类.这样只要使用策略的客户保持面向抽象类型编程,就能够使用不同的策略的具体实现对象来配置它,从而实现一系列算法可以相互替换.

何时选用

  • 出现有许多相关的类,仅仅是行为有差别的情况,可以使用策略模式来使用多个行为中的一个来配置一个类的方法,实现算法动态切换
  • 出现同一个算法,有很多不同的实现的情况,可以使用策略模式来把这些“不同的实现”实现成为一个算法的类层次
  • 需要封装算法中,与算法相关的数据的情况,可以使用策略模式来避免暴漏这些跟算法相关的数据结构
  • 出现抽象一个定义了很多行为的类,并且是通过多个if-else语句来选择这些行为的情况,可以使用策略模式来代替这些条件语句.

results matching ""

    No results matching ""