一、策略模式的定义

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

二、使用策略模式的一个例子

2.1引出问题

某公司做了一套模拟鸭子的游戏:该游戏会出现各种鸭子,他们具有相似点(都会叫,会游泳,会表达自己的特征)和异同点(每种展示自己的特征是不同的方法),很容易想到使用OO技术,定义个鸭子超类,让其他的鸭子类来继承鸭子超类。

由于异同点都会展示自己的特征,只是展示特征方式不同,所以在超类中特征的方法是抽象或者使用一个接口(在此就使用接口,因为每一个类都会有展示方法)。下面给出其类图。

可当某一天发现了问题,

问题1:如果出现了一个DuckC,展示方式和DuckA相同,都是使用相同的方法,那么就会在DuckC类中写了同样的代码,如果那一天想修改他们中的使用相同的方法,就要一个个去修改,如果是有多个的话,就容易出现问题,而且不能到达方法复用的效果。

问题2:如果想让一只鸭子需要有两种不同的展示方式,可能随时改变展示方式,上面的设计就需要修改了

2.2分析问题

问题1为了达到复用,是不可能把所有的展示方式放到Duck类中,因为对应DuckA和DuckB以及DuckC可以随便调用方法,显然是不明智的。

先把问题1放一放,我们来看一下问题2的,可以随时改变,C#中有个属性的思想不就是可以随时改变变量的值。是不是可以使用相同的方法来实现呢。每次使用set时,是让值赋给指定的变量,而且可以达到复用的目的(如Person p=new Person();p.Age=22,22是一个int类型中的一个对象,可以多次使用,而且还可以赋值为23)。一句简单的属性赋值,隐含着多种设计原则。

原则一:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

在上面一段简单的代码中,我们可以把22,23看成计算机为我们封装好的类型。22和23是被独立出来的会变化的代码。具体的实现我们不需要知道怎么实现。只需要知道表示的一个数。

原则二:针对接口编程,而不是针对实现编程。

先简单的说一下上面的意思:让变的抽象成接口或者抽象类,然后通过单独的类来把接口实现或继承抽象类来实现,而不是将功能直接在代码中实现。

在上面具体的23和22怎么的实现我们是没有直接写出new int();而是直接获取的类型,其实现交给计算机去处理。

原则三:多使用组合,少使用继承

为什么能随时“改变age”,这就是组合的力量,如果是使用继承的话,就不能在一个过程中改变age。

上面使用整型可能有些不妥,仅仅作为一中理解形式。如果非要找一下策略模式在.net中的踪影,可以看一下ArrayList的Sort(IComparer comparer)方法,可以参考http://www.cnblogs.com/justinw/archive/2007/02/06/641414.html

有了这三个原则,我觉得上面的两个问题应该可以解决了。

2.3解决问题

使用组合和属性的设计方法来处理

下面列出测试代码:

         Duck dA = new DuckA();
IDisplay displayA= dA.GetDisplay();
displayA.Display();
Console.WriteLine("A类鸭子展示方法:"); Console.WriteLine("================================"); Duck dB = new DuckB();
IDisplay displayB = dB.GetDisplay();
Console.WriteLine("B类鸭子展示方法:"); displayB.Display();
Console.WriteLine("================================"); Duck dC = new DuckC();
IDisplay displayC = dC.GetDisplay(); Console.WriteLine("C类鸭子展示方法:"); displayC.Display();
Console.WriteLine("================================");
dC.SetDisplay(new DisplayClassA());
Console.WriteLine("C类鸭子改变方法后展示方法:");
dC.GetDisplay().Display();
Console.Read();

输出结果:

三、策略模式对应的UML

该模式也体现了面向对象的基本特征:封装(把算法一个个封装起来),继承(接口的实现也可以看成是实现类“继承”了接口),多态(在Context调用接口的时间,开始并不知道接口的方法的具体实现,但是知道有个方法,使用的时间就可获取,调用)。

源码  

四、小结

本文主要通过鸭子的设计,引出问题,分析问题,解决问题来体现了策略模式的灵活性,在分析过程中提出了三个设计原则,结合属性的实现思想来解决了问题。本文是属于读书笔记,可能在理解的地方有偏差,希望能够多多指教!

Head First 设计模式读书笔记(1)-策略模式的更多相关文章

  1. head first 设计模式读书笔记 之 策略模式

    作为一个php开发者,深知曾经很多程序员都鄙视php,为什么呢?因为他们认为php的语法是dirty的,并且由于开发者水平参差不齐导致php的代码更加乱上加乱,维护起来简直一坨shit一样.随着php ...

  2. HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern)

    策略模式(Strategy Pattern): 定义了了算法簇,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户端. 第一个设计原则:找出应用中可能需要变化之处,把他们独立 ...

  3. HeadFirst设计模式读书笔记之策略模式

    1. 例子 1. 做一个鸭子模拟器,里面有很多不同的鸭子,有的可以游泳,有的可以睡觉,有的可以呱呱叫,一般套路是定义一个鸭子的超类,在 超类里定义睡觉,游泳,呱呱叫的方法,再让不同的鸭子子类继承这个超 ...

  4. 《JavaScript设计模式与开发实践》读书笔记之策略模式

    1.策略模式 定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换 1.1 传统实现 根据工资基数和年底绩效来发送年终奖 var calculateBonus= function (perfo ...

  5. HeadFirst设计模式读书笔记(4)-工厂模式

    工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个.工厂方法让类把实例化推迟到子类. 所有工厂模式都用来封装对象的创建.工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象 ...

  6. HeadFirst设计模式读书笔记之工厂模式

    1. 简单工厂 1. 你开了一家披萨店,点披萨的方法可能是这样: public Pizza orderPizza(String type) { Pizza pizza; if (type.equals ...

  7. Java 设计模式学习笔记1——策略模式(Duck例子)

    0.假设现有工程(Duck)中遇到为类添加功能的问题,如何设计类添加新的功能? 1.利用继承提供的Duck(鸭子)的行为会导致哪些缺点? (1)代码在多个子类中重复 (2)很多男知道所有鸭子的全部行为 ...

  8. HeadFirst设计模式读书笔记--目录

    HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern) HeadFirst设计模式读书笔记(2)-观察者模式(Observer Pattern) HeadFirst设计 ...

  9. JavaScript设计模式与开发实践 - 策略模式

    引言 本文摘自<JavaScript设计模式与开发实践> 在现实中,很多时候也有多种途径到达同一个目的地.比如我们要去某个地方旅游,可以根据具体的实际情况来选择出行的线路. 如果没有时间但 ...

随机推荐

  1. Spark GraphX 的数据可视化

    概述 Spark GraphX 本身并不提供可视化的支持, 我们通过第三方库 GraphStream 和 Breeze 来实现这一目标 详细 代码下载:http://www.demodashi.com ...

  2. JPA实体继承实体的映射策略

    注:这里所说的实体指的是@Entity注解的类 继承映射使用@Inheritance来注解.它的strategy属性的取值由枚举InheritanceType来定义(包含SINGLE_TABLE.TA ...

  3. 微信小程序+PHP:动态显示项目倒计时(格式:4天7小时58分钟39秒)

    1.一般我们说的显示秒杀都是指的单条数据,循环我没做. 效果: 2.wxml代码: <p class="endtime_act">距报名截止还有: <block ...

  4. Eclipse折叠代码 coffee bytes code folding

    提供一个插件下载地址,博客园的: http://files.cnblogs.com/wucg/com.cb.eclipse.folding_1.0.6.jar.zip  将下载的zip文件解压出来的j ...

  5. C#中?和:?和??总结

    ?代表可空类型修饰符    引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.为了使值类型也可为空,就可以使用可空类型?:三元表达式    int a=b>c?b:c 如果b大 ...

  6. Python学习笔记015——readline与readlines的区别

    示例1 读取同样一个文件binary_read_1.txt. 春眠不觉晓,处处闻啼鸟. 夜来风雨声,花落知多少. 其中该文件内容被下段代码读出(注意,这里是采用的readlines) f = open ...

  7. Linux内核(3) - 分析内核源码如何入手(下)

    下面的分析,米卢教练说了,内容不重要,重要的是态度.就像韩局长对待日记的态度那样,严谨而细致. 只要你使用这样的态度开始分析内核,那么无论你选择内核的哪个部分作为切入点,比如USB,比如进程管理,在花 ...

  8. LeetCode总结 -- 一维数据合并篇

    合并是一维数据结构中非经常见的操作, 一般是排序, 分布式算法中的子操作. 这篇总结主要介绍LeetCode中关于合并的几个题目: Merge Two Sorted ListsMerge Sorted ...

  9. win7下安装ubuntu双系统的方法及心得体会(ps:要死好几回的节奏)

    1.win7下安装ubuntu系统后,可以很好进入ubuntu系统 但是进不去win7,开机有win7选项,但是选择后不管用 方法思路:各种修复win7的mbr 我的问题是:在winpe中发现,根本看 ...

  10. python标准库介绍——27 random 模块详解

    ==random 模块== "Anyone who considers arithmetical methods of producing random digits is, of cour ...