在现实生活中常常遇到实现某种目标存在多种策略可供选择的情况,例如,出行旅游可以乘坐飞机、乘坐火车、骑自行车或自己开私家车等,超市促销可以釆用打折、送商品、送积分等方法。

在软件开发中也常常遇到类似的情况,当实现某一个功能存在多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能,如数据排序策略有冒泡排序、选择排序、插入排序、二叉树排序等。

如果使用多重条件转移语句实现(即硬编码),不但使条件语句变得很复杂,而且增加、删除或更换算法要修改原代码,不易维护,违背开闭原则。如果采用策略模式就能很好解决该问题。

策略模式的定义与特点

策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

策略模式的主要优点如下。

  1. 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句,如 if...else 语句、switch...case 语句。
  2. 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
  3. 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
  4. 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
  5. 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。

其主要缺点如下。

  1. 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
  2. 策略模式造成很多的策略类,增加维护难度。

策略模式的结构与实现

策略模式是准备一组算法,并将这组算法封装到一系列的策略类里面,作为一个抽象策略类的子类。策略模式的重心不是如何实现算法,而是如何组织这些算法,从而让程序结构更加灵活,具有更好的维护性和扩展性,现在我们来分析其基本结构和实现方法。

1. 模式的结构

策略模式的主要角色如下。

  1. 抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
  2. 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
  3. 环境(Context)类:持有一个策略类的引用,最终给客户端调用。

其结构图如图 1 所示。

图1 策略模式的结构图

2. 模式的实现

策略模式的实现代码如下:

public class StrategyPattern {public static void main(String[] args) {Context c = new Context();Strategy s = new ConcreteStrategyA();c.setStrategy(s);c.strategyMethod();System.out.println("-----------------");s = new ConcreteStrategyB();c.setStrategy(s);c.strategyMethod();}
}//抽象策略类
interface Strategy {public void strategyMethod(); //策略方法
}//具体策略类A
class ConcreteStrategyA implements Strategy {public void strategyMethod() {System.out.println("具体策略A的策略方法被访问!");}
}//具体策略类B
class ConcreteStrategyB implements Strategy {public void strategyMethod() {System.out.println("具体策略B的策略方法被访问!");}
}//环境类
class Context {private Strategy strategy;public Strategy getStrategy() {return strategy;}public void setStrategy(Strategy strategy) {this.strategy = strategy;}public void strategyMethod() {strategy.strategyMethod();}
}

程序运行结果如下:

具体策略A的策略方法被访问!
-----------------
具体策略B的策略方法被访问!

策略模式的应用场景

策略模式在很多地方用到,如 Java SE 中的容器布局管理就是一个典型的实例,Java SE 中的每个容器都存在多种布局供用户选择。在程序设计中,通常在以下几种情况中使用策略模式较多。

  1. 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。
  2. 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。
  3. 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。
  4. 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构。
  5. 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。

策略模式的扩展

在一个使用策略模式的系统中,当存在的策略很多时,客户端管理所有策略算法将变得很复杂,如果在环境类中使用策略工厂模式来管理这些策略类将大大减少客户端的工作复杂度,其结构图如图 5 所示。

图5 策略工厂模式的结构图

进阶阅读

如果您想深入了解策略模式,可猛击阅读以下文章。

  • 《使用策略模式实现电商多种促销优惠方案选择》
  • 《使用策略模式实现支付方式选择场景》
  • 《策略模式在JDK源码中的应用》
  • 《策略模式在Spring源码中的应用》

策略模式(Strategy模式)相关推荐

  1. STRATEGY模式(冒泡算法为例)

    STRATEGY模式 STRATEGY模式使用了一种非常不同的方法来倒置通用算法和具体实现之间的依赖关系. 不是将通用的应用算法放进一个抽象基类中,而是将它放进一个名为BubbleSorter的具体类 ...

  2. 设计模式之策略模式(Strategy)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  3. 8.6 GOF设计模式四: 策略模式… Strategy Pattern

    策略模式- Strategy Pattern  在POS系统中,有时需要实行价格优惠, 该如何处理?  对普通客户或新客户报全价  对老客户统一折扣5%  对大客户统一折扣10%  注:课件 ...

  4. 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

    设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕 ...

  5. 策略模式(Strategy Pattern)

    算法与对象的耦合:     对象可能经常需要使用多种不同的算法,但是如果变化频繁,会将类型变得脆弱...             动机:     在软件构建过程中,某些对象使用的算法可能多种多样,经常 ...

  6. 设计模式--策略(Strategy)模式

    模式定义 定义一系列算法,把它们一个个封装起来,并且使它们可互相替换(变化),该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化) 类图 要点总结 Strategy及其子类为组件提供了 ...

  7. 策略模式(Strategy)简介

    一, 回顾简单工厂模式(SimpleFactory) 上一篇博文: http://blog.csdn.net/nvd11/article/details/41855937 还是用回那个计算器作例子. ...

  8. 策略(strategy)模式

    Head First一书中对于策略(strategy)模式的正式定义是:策略模式定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户. 为了介绍这个算法,书中讲了 ...

  9. 趣谈设计模式 | 策略模式(Strategy):你还在使用冗长的if-else吗?

    文章目录 案例:指挥官AI 策略模式 配合工厂模式 总结 完整代码与文档 案例:指挥官AI 案例可能不符合实际逻辑,仅用于表述设计模式的思想,勿介意 假设我们开发了一款类似全面战争的即时战略游戏,为了 ...

  10. 39策略模式(Strategy Pattern)

    算法与对象的耦合:     对象可能经常需要使用多种不同的算法,但是如果变化频繁,会将类型变得脆弱...              动机:     在软件构建过程中,某些对象使用的算法可能多种多样,经 ...

最新文章

  1. binary_crossentropy(二元交叉熵)的定义
  2. Spring MVC 登录拦截器
  3. 物联网通信之Coap 协议
  4. 程序员“不会”修电脑的原因
  5. 四张类图理一下Streams的用法
  6. 进入大厂的面试经验详细总结(P7 拿 offer)
  7. 1.7 试探法(回溯法)
  8. qt tcp不可以循环发送_Qt tcp 多线程下QTCPsocket不能发送数据~解决办法(2)
  9. java 排队实现_java中的优先列队-PriorityQueue源码实现解析
  10. 斗地主Java课程设计_Java课程设计---web版斗地主
  11. node使用ffmpeg拼接音频
  12. java自制语音识别,JAVA作的语音识别
  13. python中numpy中的shape和get_shape解析
  14. matlab 将dcm文件转换为raw
  15. PiscisOS开发笔记_1_PiscisOS的诞生和系统特性简介
  16. 运用数学软件matlab求无穷积分,matlab积分的计算及其简单应用论文.doc
  17. Python 发邮件
  18. PCIe driver
  19. SAM4E单片机之旅——10、UART与MCK之PLL
  20. Window是系统中BitLocker是否应该开启?

热门文章

  1. Chrome看视频站Flash很卡的解决方法
  2. java中void的含义_void在Java-java中void后面接什么-java中关键字void的含义
  3. 大专生自学php到找到工作的前前后后
  4. 初识Java----适合网络编程的语言
  5. 向全业务融合计费平滑演进
  6. Base封装(一)--我的最简MVP架构
  7. 简单制作截图工具,你也可以
  8. docker 连接宿主机的 MySQL
  9. 绝对值得收藏的,关于癌症的文章
  10. VMware® Workstation 15 Pro 无法从iso文件安装系统