策略模式的用意是针对一组算法,将每个算法封装到具备共同接口的独立的类中,从而使得它们能够相互替换。策略模式使得算法能够在不影响到客户端的状况下发生变化。算法
假 设如今要设计一个贩卖各种书籍的电子商务网站的购物车(Shopping Cat)系统。一个最简单的状况就是把全部货品的单价乘上数量,可是实际状况确定比这要复杂。好比,本网站可能对全部的教材类图书实行每本一元的折扣;对 连环画类图书提供每本7%的促销折扣,而对非教材类的计算机图书有3%的折扣;对其他的图书没有折扣。因为有这样复杂的折扣算法,使得价格计算问题须要系 统地解决。设计模式
使用策略模式能够把行为和环境分割开来。环境类负责维持和查询行为类,各类算法则在具体策略类 (ConcreteStrategy)中提供。因为算法和环境独立开来,算法的增减、修改都不会影响环境和客户端。当出现新的促销折扣或现有的折扣政策出 现变化时,只须要实现新的策略类,并在客户端登记便可。策略模式至关于"可插入式(Pluggable)的算法"。ide
策略模式是对算法的包装,是把使用算法的责任和算法自己分割开,委派给不一样的对象管理。策略模式一般把一个系列的算法包装到一系列的策略类里面,做为一个抽象策略类的子类。用一句话来讲,就是:"准备一组算法,并将每个算法封装起来,使得它们能够互换。"oop
策略又称作政策(Policy)模式【GOF95】。下面是一个示意性的策略模式结构图:学习
这个模式涉及到三个角色:网站
在学习策略模式时,学员常问的一个问题是:为何不能从策略模式中看出哪个具体策略适用于哪种状况呢?ui
答案很是简单,策略模式并不负责作这个决定。换言之,应当由客户端本身决定在什么状况下使用什么具体策略角色。策略模式仅仅封装算法,提供新算法插入到已有系统中,以及老算法从系统中"退休"的方便,策略模式并不决定在什么时候使用何种算法。this
下面的例子利用策略模式在排序对象中封装了不一样的排序算法,这样以便容许客户端动态的替换排序策略(包括Quicksort、Shellsort和Mergesort)。spa
在下面的状况下应当考虑使用策略模式:设计
1. 若是在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式能够动态地让一个对象在许多行为中选择一种行为。
2. 一 个系统须要动态地在几种算法中选择一种。那么这些算法能够包装到一个个的具体算法类里面,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算 法类均有统一的接口,因为多态性原则,客户端能够选择使用任何一个具体算法类,并只持有一个数据类型是抽象算法类的对象。
3. 一个系统的算法使用的数据不可让客户端知道。策略模式能够避免让客户端涉及到没必要要接触到的复杂的和只与算法有关的数据。
4. 若是一个对象有不少的行为,若是不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就能够避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念。
策略模式有不少优势和缺点。它的优势有:
1. 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承能够把公共的代码移到父类里面,从而避免重复的代码。
2. 策 略模式提供了能够替换继承关系的办法。继承能够处理多种算法或行为。若是不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每个子类提供 一个不一样的算法或行为。可是,这样一来算法或行为的使用者就和算法或行为自己混在一块儿。决定使用哪种算法或采起哪种行为的逻辑就和算法或行为的逻辑混 合在一块儿,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。
3. 使用策略模式能够避免使用多重条件转移语句。多重转移语句不易维护,它把采起哪种算法或采起哪种行为的逻辑与算法或行为的逻辑混合在一块儿,通通列在一个多重转移语句里面,比使用继承的办法还要原始和落后。
策略模式的缺点有:
1. 客户端必须知道全部的策略类,并自行决定使用哪个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道全部的算法或行为的状况。
2. 策略模式形成不少的策略类。有时候能够经过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例能够被不一样客户端使用。换言之,可使用享元模式来减小对象的数量。
策 略模式与不少其它的模式都有着普遍的联系。Strategy很容易和Bridge模式相混淆。虽然它们结构很类似,但它们倒是为解决不一样的问题而设计的。 Strategy模式注重于算法的封装,而Bridge模式注重于分离抽象和实现,为一个抽象体系提供不一样的实现。Bridge模式与Strategy模 式都很好的体现了"Favor composite over inheritance"的观点。
推荐你们读一读《IoC 容器和Dependency Injection 模式》,做者Martin Fowler。网上能够找到中文版的PDF文件。为策略模式的实施提供了一个很是好的方案。
参考文献: 阎宏,《Java与模式》,电子工业出版社 [美]James W. Cooper,《C#设计模式》,电子工业出版社 [美]Alan Shalloway James R. Trott,《Design Patterns Explained》,中国电力出版社 [美]Robert C. Martin,《敏捷软件开发-原则、模式与实践》,清华大学出版社 [美]Don Box, Chris Sells,《.NET本质论 第1卷:公共语言运行库》,中国电力出版社