软件设计模式学习(二十五)策略模式


策略模式用于算法的自由切换和扩展,实现了算法定义和算法分离的使用html


模式动机

要完成一项任务,能够有多种不一样的方式,例如人们外出旅游时能够选择多种不一样的出行方式,如自行车、坐汽车、坐高铁或乘飞机等,每一种方式称为一个策略,咱们能够根据环境或者条件的不一样选择不一样的策略来完成该任务。java

在实际的软件开发中,一项功能也有不少算法能够实现,若是咱们直接把多种算法集中在一个类,或者说使用条件判断语句来进行选择,无疑会增长代码复杂性,不利于维护。算法

为了解决这些问题,能够定义一些独立的类来封装不一样的算法,每一类封装一个具体的算法,将每个封装算法的类称之为策略(Strategy)。为了保证策略的一致性,通常会用一个抽象的策略类来作算法的定义,每种具体算法对应于一个具体策略类。编程


模式定义

策略模式(Strategy Pattern)定义一系列算法,将每一个算法封装起来,并让它们能够相互替换。策略模式让算法独立于使用它的客户而变化,也称政策模式(Policy)。策略模式是一种对象行为模式。this

Define a famliy of algorithms, encapsulate each one,and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.设计


模式分析

说到策略模式就不得不提一下状态模式了,一个是对状态的封装,另外一个则是对算法的封装,所以实现方式上二者有许多共同点,理解起来并不复杂code

点这里了解状态模式htm

策略模式是对算法的封装,把算法的责任和算法自己分割开来,委托给不一样对象管理。策略模式一般把一系列算法封装到一系列的策略类里面,做为一个抽象策略类的子类。对象

由此能够得出结构类图以下:blog

环境类(Context)是须要使用算法的对象,它在解决某个问题时能够采用多种策略,在环境类中维护一个对抽象策略类的引用实例,用于定义所采用的策略。假如咱们不使用策略模式,可能会存在以下代码:

public class Context {
    ...
    public void algorithm(String type) {
		...
         if(type == "strategyA") {
             // 算法A
         } else if(type == "strategyB") {
             // 算法B
         } else if(type == "strategyC") {
             // 算法C
         }
        ...
    }
    ...
}

客户端要调用 Context 类的 algorithm() 方法时,须要根据所传入的参数来选择具体算法,这将致使代码过于庞大,不利于维护。并且最大的问题是,在环境类中定义算法,若是须要修改或增长算法,则势必要修改源代码,违反了开闭原则。

致使以上问题的主要缘由在于环境类职责太重,即违背了单一职责原则,策略模式正是解决这个问题的好帮手。引入一个抽象策略类(Strategy),在其中定义抽象算法,每个继承它的具体策略类(ConcreteStrategy)使用具体算法实现某个业务办理。环境类只针对抽象策略类编程,符合依赖倒转原则,出现新的算法时,只须要增长一个新的实现了抽象策略类的具体策略类便可。

public abstract class AbstractStrategy {
	public abstract void algorithm();
}

将每一种具体算法做为该抽象策略类的子类

public class ConcreteStrategyA extends AbstractStrategy {
	public void algorithm() {
        // 算法A
    }
}

对于环境类,在它与抽象策略类之间创建一个关联关系

public class Context {
    private AbstractStrategy strategy;
    public void setStrategy(AbstractStrategy strategy) {
        this.strategy = strategy;
    }
    public void algorithm() {
        strategy.algorithm();
    }
}

对于用户而言,使用环境类时只需注入一个具体策略对象便可。用户能够灵活更换具体策略类,好比使用配置文件,增长新的具体策略类也很方便,所以策略模式至关于“即插即用的算法”。

须要注意的是,策略模式并不负责“哪个具体策略类适用于哪种状况”这个决定,换言之,应当由客户决定在什么状况下使用什么具体策略角色,必定程度上提升了系统灵活性,但前提是客户须要理解因此具体策略类之间的区别及最佳使用场景。

对比状态模式,状态模式能够实现自主的状态切换,并根据状态的不一样作出不一样的行为。而


模式优缺点

策略模式的优势:

  • 策略模式提供了对开闭原则的完美支持,将算法的使用与实现完美分离,用户能够在不修改原有系统的基础上选择和新增算法
  • 策略模式的等级结构定义了一个算法族,恰当使用继承能够把公共的代码移到父类里面,避免重复代码
  • 能够避免使用多重条件转移语句

策略模式的缺点:

  • 客户端必须知道全部的策略类,并自行决定使用哪种算法
  • 策略模式将产生不少策略类和对象,能够经过享元模式在必定程度上减小对象的数量

策略模式与状态模式的比较

因为结构的类似性,因此很容易会把策略模式和状态模式混肴,但它们是为解决不一样的问题而设计的,是彻底不一样的两种模式。如何区分是策略模式仍是状态模式?其区别以下:

  • 若是环境角色存在多种状态,并且这些状态之间能够进行转换,则应使用状态模式,在状态模式在,环境类在生命周期中,会有一个不一样的状态对象被建立和使用;若是环境角色只有一个状态,那么应当使用策略模式,由于一旦环境角色选择了一个具体策略类,那么在整个环境类的生命周期里它都不会改变这个具体策略类
  • 策略模式的环境类本身选择一个具体策略类,具体策略类无须关心环境类;状态模式的环境类与状态类之间存在一种双向关系,以便实现状态的切换
  • 使用策略模式,客户端须要知道所选的具体策略模式是哪个,而使用状态模式,客户端无须关心具体状态,环境类的状态会根据用户的操做自动转换
  • 若是系统中某个类的对象存在多种状态,不一样状态下行为有差别,并且这些状态之间能够发送转换时使用状态模式;若是某个类的行为存在多种实现方式,并且这些方式能够互换时使用策略模式
相关文章
相关标签/搜索