设计模式-策略设计模式(一)

本文大幅度参考Head first设计模式中第一章.

先来看一个简单的模拟鸭子应用做起,某公司做了一套模拟鸭子游戏:SimUDuck.游戏中出现各种鸭子,一边游泳戏水,一边呱呱叫.此系统的内部设计使用了标准OOP思想,设计了一个鸭子超类(Superclass),并让各种鸭子继承此超类.类图如下:

  

为了提升产品的竞争力,高层决策,此模拟程序需要会飞的鸭子.作为一个面向对象的程序员,解决这个问题似乎很easy.只需要在Duck类中添加fly().

问题真的是这样吗?想想如果我们在Duck类中增加fly(),也就表示所有Duck的子类都会飞.而Duck的一个子类[橡皮鸭子并不需要飞的行为].当然,我们覆盖橡皮鸭子的fly()为空实现.如果以后还会增加其他不会飞也不会叫的鸭子呢?

此时,我们应该认真思考下继承所带来的缺点:在父类中增加的非私有属性和方法会强制加给子类,给子类带来了不想要的改变,对父类的改变可能会牵一发而动全身,对以后的扩展相当麻烦.那么,利用接口又如何呢?看下面的类图:

 接口可以解决部分问题,但是如果Duck有多个子类都具备相同的fly行为,那么岂不是要将一个fly方法写多次?

我们知道,并非所有的子类都具有飞行和呱呱叫的行为,所以继承并不是适当的解决方式.虽然Flyable和Quackable可以解决某一些子类的问题(不会再有会飞的橡皮鸭),但是确造成了代码无法复用,这算是从一个恶梦跳进另外一个恶梦.甚至,在会飞的鸭子中,飞行的动作可能还有多种变化.

现在我们殷切希望有一种建立软件的方法,让我们需要改变软件时,可以在对既有的代码影响最小的情况下,轻易达到花较少时间重做代码,而多让程序去做更酷的事情该有多好...

软件开发一个不变的真理:change.不管当初软件设计得多好,一阵子以后,总是需要成长与改变,否则软件就会[死亡].

现在我们知道使用继承有一些缺失,因为改变鸭子的行为会影响所有鸭子的子类,而这并不恰当.Flyable与Quackable接口一开始似乎还挺不错哦,解决了问题(只有会飞的鸭子继承Flyable),但是Java接口并不能实现代码,所以继承接口无法达到代码的复用.这意味着:无论何时你需要修改某个行为,你必须往下追踪并修改每一个定义此行为的类,一不小心,可能造成新的错误.幸运的是,有一个设计原则,适用于这种状况:

  设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不要变化的代码混在一起.专业点的说法:封装变化的部分,好让其他部分不会受到影响.
     当代码变化之后,出其不意的部分变得很少,系统变得更有弹性。

换句话说,如果每次新的需求,都会变化到某方面的代码,那么就可以确定这部分代码需要被抽出来,和其他不变动的代码隔离.这样的概念很简单,几乎是每个设计模式背后的精神所在.所有模式都提供一套方法让[系统中某部分改变不会影响其他部分].

现在我们把鸭子的行为从Duck类中取出来!就目前所知除了fly()和quack()的问题之外,Duck类还算一切正常,似乎没有特别需要经常变化和修改的地方.所以除了某些小改变之外,我们不打算对Duck类做太多处理.现在,为了抽出变化的部分,我们建立两组类(完全远离Duck类),一个是fly相关的,一个是quack相关的,每一组类将各自实现各自的动作,比方说,我们可能有一个类实现呱呱叫,一个类实现吱吱叫,一个类实现安静.

我们希望一切能有弹性,毕竟,正是因为一开始的鸭子行为没有弹性,才发生现在的问题.我们还想能够指定行为到鸭子的实例,比如说,想要产生绿头鸭.并指定特定的飞行类型给它.也就是让鸭子的行为可以动态变化.换句话说,我们应该在鸭子类中包含设定行为的方法,就可以在运行时动态改变绿头鸭的飞行行为.有了这个目标,看第二个设计原则:

  设计原则:针对接口编程,而不是针对实现编程.

我们来看新的设计.

  

这样的设计,可以让飞行和呱呱叫的动作被其他的对象复用,因为这些行为已经与鸭子类无关了.就算增加一些行为也不会影响到既有的行为类,也不会影响有使用到飞行行为的鸭子类.这样一来,有了继承的好处[复用],也摈弃了继承所带来的缺点.

ok,讲了这么多.就是为了引出策略设计模式(Strategy Pattern).为了介绍这个模式,我们走了很长一段路,下面是这个模式的正式定义:

  策略模式:定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户.

关于策略模式的思考和总结以及应用请看设计模式-策略模式(二)。

时间: 2024-08-27 06:03:06

设计模式-策略设计模式(一)的相关文章

mongodb设计模式策略之读书笔记

mongodb的设计模式策略 读书笔记 1.查询命令分类模式 在副本集中职责被分离到不同的节点.最基本的第一类节点可能也同时占据着首要地位,它只需要储存那些写入和更新所需的数据.而查询工作则交由第二类节点来执行.这一模式将提升首要节点服务器的写吞吐量,因为当写入一组对象时,需要更新及插入的数据量也随之减少,除此之外,二类节点也得益于较少的待更新数据和其自身所具有的为其工作量而优化的内存工作集. 也就是读写分离,主节点写,备节点做查询. 2.应用程序式事务模式 使用queue 样例 db.queu

设计模式之策略设计模式

一.何为策略设计模式呢? 在我的理解中,策略模式是尽量使用组合而非继承来实现一个行为,对一个方法的进行封装来使用,在组合类中进行调用时能够随时改变这一方法的运行时的内容.下面让我们来看看将一个实现改成策略模式后的便捷性. 二.一个简单的示例 假设我们有一个抽象的人,他拥有会踢球跟会乐器的技能,然后有一个只会踢球不会乐器的人继承了这个抽象的人类,还有一个只会乐器不会踢球的人继承了这个抽象的人类. 1 abstract class People{ 2 abstract void playBall()

接口的常用用法都有什么?策略设计模式复习总结

从之前的一个总结性话题引出: 从接口.抽象类到工厂模式再到JVM来总结一些问题 涉及的知识点总结如下: 策略模式概念和例子 工厂模式和策略模式比较 策略模式优缺点 策略模式的意义 使用了策略模式的API——HttpServlet类分析 解决策略膨胀问题——享元模式 StrategyPattern:策略模式也算比较简单的,同工厂模式一样都属于面向接口编程……策略模式是对象的行为模式之一,而工厂模式是对象的创建模式!它对一系列的算法加以封装,为所有算法定义一个抽象的算法接口,并通过继承该抽象算法接口

设计模式 - 策略模式(Strategy Pattern) 具体解释

策略模式(Strategy Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26577879 本文版权全部, 禁止转载, 如有须要, 请站内联系. 策略模式: 定义了算法族, 分别封装起来, 让它们之间能够相互替换, 此模式让算法的变化独立于使用算法的客户. 对于父类的子类族须要常常扩展新的功能, 为了使用父类比較灵活的加入子类, 把父类的行为写成接口(interface)的形式; 使用set()方法

设计模式 - 策略模式(Strategy Pattern) 详解

策略模式(Strategy Pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26577879 本文版权所有, 禁止转载, 如有需要, 请站内联系. 策略模式: 定义了算法族, 分别封装起来, 让它们之间可以相互替换, 此模式让算法的变化独立于使用算法的客户. 对于父类的子类族需要经常扩展新的功能, 为了使用父类比较灵活的添加子类, 把父类的行为写成接口(interface)的形式; 使用set()方法,

策略设计模式理解

我们开发过程中,常因为一开始的架构不怎么合理而有可能造成后边客户或者项目经理改需求时,造成我们需要修改原来的代码,一方面是可能写的时间久了回顾起来麻烦,另一方面是牵一发而动全身,改动一个地方造成所有的地方都需要改动,由此可见一个好的架构是多么重要.那么今天给大家讲一种策略设计模式来定义一个利于扩展的框架. 简单举个例子,我们开发一款游戏如果有需要定义一个角色,有武器攻击,有武器防御,那我们可能会觉得很简单,然后一开始定义就直接定义一个父类,再加一个子类实现,代码如下: abstract clas

Java编程思想笔记02:组合与继承、final、策略设计模式与适配器模式、内部类、序列化控制(注意事项)

1.组合和继承之间的选择 组合和继承都允许在新的类中放置子对象,组合是显式的这样做,而继承则是隐式的做. 组合技术通常用于想在新类中使用现有类的功能而非它的接口这种情形.即在新类中嵌入某个对象,让其实现所需要的功能,但新类的用户看到的只是为新类所定义的接口,而非所嵌入对象的接口.为取得此效果,需要在新类中嵌入一个现有类的private对象.但有时,允许类的用户直接访问新类中的组合成分是极具意义的,即将成员对象声明为public.如果成员对象自身都隐藏了具体实现,那么这种做法是安全的.当用户能够了

应用策略设计模式

设计模式:设计模式(Design pattern)是一套被重复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用设计模式是为了可重用代码.让代码更easy被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的.设计模式使代码编制真正project化.设计模式是软件project的基石脉络.如同大厦的结构一样. 在最開始学习设计模式时.看着书籍,总是认为设计模式非常easy.但是.每次在实战的时候.常常渴望可以用上设计模式,但总是无法第一时间应用上某种设计模式. 明

2.大话设计模式-策略模式

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DesignModel 8 { 9 /// <summary> 10 /// 策略模式 11 /// </summary> 12 public class TacticsModel 13 { 14 //对于