原文:http://blog.sina.com.cn/s/blog_48df74430100t2m7.html

前言

部门组织培训,《Effective Java》,每人每天给大家讲解一节。但十个同事就我一个是做.Net开发的,所以每回我就是听众,前两天的一节是《用函数对象表示策略》,讲的非常短频快,但下来我的感触颇多,对代码不再有当初的激情了,但总想把平时经常用到的,别人已经总结归纳的用文字记录下来,好记性不如烂笔头,只有记录下来的才是属于自己的。于是决定从本篇开始我的设计模式之旅,这个系列3年前就有总结的想法,但一再找各种理由推托,就像戒烟一样,希望对自己来说现在不算太晚。

从Justin老兄的博客看到经典“鸭子模式”的例子,对我的启发非常大,也是参照他的例子自己胡思乱想了“飞机模式”,跟鸭子模式很像,其实也就是自己编个故事给自己听,然后从故事里能总结出来一些道理就好。鸭子模式原文地址:http://www.cnblogs.com/justinw/archive/2007/02/06/641414.html

从简单的例子开始

话说中东X国空军指挥部使用OO语言开发一款作战飞机管理系统,想把所有飞机管理起来。刚开始由于飞机数量有限,仅拥有为数不多的几架从美俄进口的战斗机,于是开发人员构建了如下的类结构:

如图所示,在“飞机”基类里实现了公共的“飞行”和“加油”方法,而“F22战斗机”和“猛禽战斗机”可以分别覆盖实现自己的“外型”方法,这样即重用了公共的部分,又支持不同子类的个性化扩展。从目前的情况看,X国国防部很满意!

过了一段时间,世界石油价格飙涨,X国高层觉得是时候再添置一批运输机了,以配合地面部队的物质补给,于是X国又采购了一批大力神运输机,空军指挥部的开发人员扩展了他们的类结构:

恩,目前仍然不错,开发人员觉得自己的设计非常棒,甚至国防部还将这个项目纳入了X国国家9527火炬计划!

然而世界局势变幻莫测,X的邻国Y国早对X的石油资源垂延三尺,终于有一天按奈不住冲动,一拥而上......大兵压境,X国十万火急向美俄购入一批导弹来武装“F22”和“猛禽”战斗机,开发人员丝毫不敢怠慢,连夜修改了他们的设计:

第二天,有了攻击系统的X国空军准备大规模反攻时,悲剧发生了,之前按战斗机数量采购的导弹居然不够用,有一半以上的战斗机在出发前居然未能装弹。国防部长来到现场发现:每架运输机机翼上居然捆了两枚价值100万美元的“小牛”空对地导弹。

当天损失惨重,总统下了最后通牒:马上修改你们的系统,三天内如果修改不好,所有人都去挖煤!

顶着压力,开发人员终于冷静下来找到了原因,原来在“飞机”基类里增加的“攻击”方法,也同样被子类“大力神运输机”给继承了,而基类里的“攻击”方法包括了装弹步骤,所以就有了运输机悬挂空对地导弹的一幕。那么该怎么办呢?有人提议:能不能在“大力神运输机”里把“攻击”方法重写一下?让它什么都不做,不就行了吗?但马上有人反对,那“F22战斗机”和“猛禽战斗机”是不是也要重写?并且以后如果再增加其它类型的教练机、预警机、运输机,是不是都要重写“攻击”方法?这太麻烦了,而且非常混乱。

大家很困惑,为什么屡试不爽的继承,在系统扩展的时候,无法很好地支持重用呢?最后经过反复讨论,决定使用接口,设计如下:

但空军指挥部马上否决了这个设计:“你们难道希望所有载有导弹的飞机都去重复实现这个方法吗?现在我们飞机少还好说,但有不久后我们有成千上万架战斗机的时候怎么办?如果导弹系统要做一点修改,难道要重复修改上万遍吗?你们是不是疯啦?”

策略模式前奏

如果你是X国的开发人员,你会怎么做?我们知道,并不是所有飞机都能攻击,所以继承不是正确的方法。虽然上面使用“攻击接口”可以解决部分问题(不再给运输机装上“小牛”空对地导弹),但是这个解决方案却彻底破坏了重用,它带来了另一个噩梦----维护!

要解决这个问题,我们必须回到设计模式的第一个原则:

Identify the aspects of your application that vary and separate them from what stays the same.(找到系统中变化的部分,将变化的部分同其它稳定的部分隔开)

什么意思?打个简单的比方,你电脑上有主板有硬盘,主板跟硬盘是可以很方便拆分开的吧。你今天可以用100G的硬盘,明天可以换500G的硬盘,硬盘就是变化部分,它根据用户需求随时都能调整;而主板上的南北桥芯片你能更换不?也许有强人能做到,但起码厂家的设计是不让你轻易更换的吧,所以这就是稳定部分。我们可以发现,其实设计模式不只针对软件,它随处可见。

Program to an interface, not an implementation.(面向接口编程,而不要面向实现编程)

这条原则应该是经常看见,它跟面向对象里的“多态”紧密相连,什么意思?我们还是继续上面电脑主板的例子,其实主板开发商早已把“面向接口”发挥的淋漓尽致了。拿主板上的USB口来说,USB口可能外接数码相机,可能外接打印机,外接键盘鼠标,外接手机,外接五花八门各种各样已经有的和未来会出现的设备。如果主板厂家为每种设备都实现一套独立的交互程序,那后果是灾难性的。于是主板厂家们使用了面向接口开发,接口早期由像IBM这样的大厂商制订,后来由一些标准化组织接管,他们在接口里声明了所有用到的标准,比如数据的传输封装格式,接口的型状,接口能接受的电压等等,主板厂家们只按照接口标准来开发自己的主板,而不用关心接口另一端连接的是什么设备。

策略模式登场

The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.(策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们可以相互替换。策略模式让算法独立于使用它的客户而独立变化。)

X国使用策略模式后的类结构图如上。

1、将变化部分跟稳定部分分离开:飞机一定是要飞行的,所以“飞行”是稳定部分;飞机一定得加油,所以“加油”是稳定部分;飞机一定会有外型,就算是隐形飞机也不例外,所以“外型”也是稳定部分。而“攻击”则有的飞机有,有的飞机没有,比如战斗机能攻击而运输机不能,所以“攻击”属变化部分,需要将其与稳定部分分离开。

2、单单分离开只是策略模式的一部分,还需要将变化部分细化、整理和抽象,此时,面向接口会是理想选择。

不谈理论,还是用实例继续,OK,经过一段时间实战,X国的空军指挥官们发现了一个奇怪的现象:苏制F22战机每次作战几乎毫发无伤,而美制的猛禽战斗机和大力神运输机却每每损失惨重。经过反复研究,他们终于发现原来F22战机拥有性能强悍的雷达系统,而美制飞机的雷达全部是Made In China,200米范围以外根本侦测不到敌机。于是他们决定花重金将所有美制飞机的雷达更换为以色列的天网系列。这回开发人员很轻易扩充了他们的另一策略:

从类图中可以发现,每个策略均是独立的,各种类型的飞机可以任意添加、删除和组合各种不同的策略。

对策略模式的总结

通过X国的模拟实例可以发现,继承的功能确实很强大,但是也存在诸多问题,因为它违背了封装原则。只有当子类和父类之间确实存在子类型关系时,使用继承才是恰当的。即便如此,如果父类不是为了继承而设计的,那么继承将会导致脆弱性,所以可以用复合来代替继承,这一点在策略模式中尤其重要。同时这也是本文的最后一个非常重要的设计原则:Favor composition over inheritance.(优先使用对象组合,而非类继承)

转载于:https://www.cnblogs.com/tk091/p/3476316.html

(转载)设计模式之-策略模式(Strategy)相关推荐

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

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

  2. 二十四种设计模式:策略模式(Strategy Pattern)

    策略模式(Strategy Pattern) 介绍 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.本模式使得算法的变化可独立于使用它的客户. 示例 有一个Message实体类,对它的操 ...

  3. 锈才学设计模式之 —— 策略模式(Strategy Pattern)

    锈才学设计模式之  -- 策略模式 策略模式:把功能提供者单独封装成类,使它们可以互相替换使用,让功能提供者独立于使用者(调用者). 说明: 在面向对象编程中,我们尽量将功能(类)设计成复用,以符合O ...

  4. 设计模式实战-策略模式(Strategy Pattern)

    0 联系我 图片标题 1.Q群[Java开发技术交流]:jq.qq.com/?_wv=1027&a- 2.完整博客链接:www.shishusheng.com 3.知乎:www.zhihu.c ...

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

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

  6. 设计模式之策略模式(strategy)--游戏角色使用武器

    策略模式:定义了算法族,并且让算法之间可以相互替换,它可以将算法实现和算法的使用客户独立. 转载于:https://www.cnblogs.com/beyondwcm/archive/2007/11/ ...

  7. Java设计模式之——策略模式(Strategy)

    一.例子 令狐冲被岳不群罚在思过崖上面壁思过.偶然的机会发现崖内有一个后洞,石壁上刻有魔教十长老尽破五岳剑派的图形招式.所有五岳剑派引以为豪的精微奥妙招式尽数被破得干干净净,包括一些已经失传的招式. ...

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

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

  9. 解读设计模式----策略模式(Strategy Pattern)

    一.模式概述      策略模式(Strategy Pattern)在外形上与状态模式很相似,但在意图上有些不同.其意图是使这些算法可以相互替换,并提供一种方法来选择最合适的算法.       在我应 ...

  10. 揭秘设计模式:策略模式(Strategy)的枚举(Enum)实现

    2019独角兽企业重金招聘Python工程师标准>>> 链接地址:http://www.xx566.com/detail/120.html 上一篇:揭秘设计模式:策略模式(Strat ...

最新文章

  1. 基于ESP32的竞赛裁判系统功能调试-硬件修改建议
  2. python 优秀文章索引
  3. 河南测绘职业学院招生计算机,河南测绘职业学院代码
  4. Mysql:增加用户和密码,赋予权限
  5. centos rpm mysql 5.6_centos6.5 mysql5.6 RPM安装
  6. 关于ThreadPool.RegisterWaitForSingleObject和WaitHandle的应用介绍
  7. 通过常用监控命令快速发现性能问题
  8. 深入解读Linux内存管理系列(3)——MMU初始化和页表的建立
  9. 简单了解Java语言
  10. Visio搜索形状显示无匹配项的解决方法
  11. 10分钟搭建树莓派NAS私有云和KODI影音播放系统 (2)---软硬搭配干活不累
  12. ubuntu 命令行 ocr 双层pdf OCRmyPDF
  13. Java多线程面试攻略(一)
  14. lambda演算感想之规则
  15. 台式计算机usb口不能用,电脑usb接口不能用怎么办【图文教程】
  16. html中加好看的边框,html – CSS3中的嵌入边框很好
  17. 阶跃信号的matlab,单位阶跃信号的表示-matlab
  18. 我们“潜”入了百度最大的数据中心,看看它长什么样
  19. 11210怎么等于24_小学二年级的巧算24点.docx
  20. antd pro学习入门笔记+todolist实例

热门文章

  1. CUDA C编程权威指南 第八章 多GPU编程
  2. 编程通用知识 系统编程
  3. 笔记本电脑网络连接显示红叉_物联网设备的网络连接---上篇
  4. 华为RH2288v3服务器安装ESXI 6.7U3(转载)
  5. VMware NSX组件构建矩阵
  6. Docker 学习总结(71)—— Docker、Docker Compose、Docker Swarm 之间的区别
  7. Docker学习总结(39)——简析容器、无服务器和虚拟机的安全性差异
  8. Java Web学习总结(23)——Distributed Configuration Management Platform(分布式配置管理平台)
  9. 安卓能不能安装jar_PyCharm 2019安装教程
  10. Android彻底组件化方案实践