今天是五.四青年节,祝大家节日快乐。看着今天这标题就有食欲,夏天到了,醋溜土豆丝和清炒苦瓜适合夏天吃,好吃不上火。这两道菜大部分人都应该吃过,特别是醋溜土豆丝,作为“鲁菜”的代表作之一更是为大众所熟知,醋溜土豆丝,好吃不上火。清炒苦瓜这道菜好啊,更是夏天必备之良菜,其功效在此就不做过多赘述了。言归正传,上篇博客我们从“小弟”中学习了“外观模式”,我们也把“外观模式”戏称为“小弟模式”。今天我们要从醋溜土豆丝和清炒苦瓜的制作过程中来学习一下我们今天博客的主题“模板方法模式”(Template Method Pattern)。

说到模板方法模式,如果你看过之前发表的重构相关的博客的话,应该对模板方法模式并不陌生。在《代码重构(五):继承关系重构规则》这篇博客中第三部分,其实是使用的“模板方法模式”进行重构的,在重构规则里边我们称之为“Form Template Method (构造模板函数)”,这个模板函数就是我们本篇博客中的模板方法。今天我们要从另一个角度来看一下“模板方法模式”,并从“醋溜土豆丝”和“清炒苦瓜”的制作实例中来学习一下“模板方法模式”。在本篇博客中,你不仅是一位Programer,还是一位Cook。

老规矩,在博客的开头,我们先给出“模板方法模式”的定义。如果你是小白,定义看不懂没关系,因为定义一般都比较难理解。你可以看完下方的具体实例后在回头看这个定义即可。模板方法的定义如下:

模板方法模式:在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

一、开始炒菜

接下来我们将要开始制作我们的醋溜土豆丝和清炒苦瓜这两道菜,当然在本篇博客的第一部分我们不会使用我们的模板方法来炒菜的。我们在该部分先给出常规的做菜的方法,然后我们会对其分析,最终会使用我们的“模板方法模式”来进行炒菜。当然在此我们不是真的用锅炒菜了,而是用我们的代码来炒菜,走起。

1.炒一个醋溜土豆丝

接下来我们要炒一个醋溜土豆丝,醋溜土豆丝好吃,做起来又简单。还是那句话,醋溜土豆丝,好吃不上火。因为炒“醋溜土豆丝”我们是在一个类中完成的,所以在此就不画类图了,等下发使用模板方法模式后,在给出相应的类图。下方的FryShreddedPotatoes类就是我们做“醋溜土豆丝”的类。其中给出了做醋溜土豆丝的一系列的步骤,并且在fryShreddedPotatoes()函数中对这一系列的函数进行了组合。

上面完成的这个类,我们就可以将上述这个类进行实例化并调用fryShreddedPotatoes()来炒一盘醋溜土豆丝了。下方我们就将FryShreddedPotatoes进行实例化,然后炒了一盘醋溜土豆丝。

2、来一盘“清炒苦瓜”

上面土豆丝炒完了,已出锅。接下来我们还要来一盘“清炒苦瓜”,当然“清炒苦瓜”的做法和上面“醋溜土豆丝”差不过,不过有些步骤还是不同的。当然你在炒苦瓜的时候不能放醋了,还有在炒苦瓜的时候你放的是苦瓜片而不是土豆丝了,这些都是不同的。当然两者的菜名也不一样呢。下方这个类就是我们“清炒苦瓜”的类,你可以将该类进行实例化然后去做一盘属于你的清炒苦瓜。大体上一看,下方的代码与上面我们醋溜土豆丝的类的步骤差不多,但是具体细节,以及一些步骤所调用的方法所不同。下方就是我们清炒苦瓜的类,如下所示:

接着就是来实例化上面“清炒苦瓜”的类,然后来一盘清炒苦瓜。下方是我们创建的上面的类的对象,然后去调用炒苦瓜的方法。下方是调用方式和输出结果,经过下方的过程,我们就可以出锅一盘清炒苦瓜了,如下所示:

二、使用“模板方法”来炒菜

在上面两种炒菜的方法中,我们不难看出炒醋溜土豆丝和清炒苦瓜中的类中有好多重复的代码。在我们重构系列中的博客中我们已经提到切记重复代码,所以我们要对上面的两个类进行代码的重构,而重构的方式就是使用“模板方法模式”来进行重构。本质上就是将变的部分与不变的部分进行分离,在该实例中变的部分就是某些步骤的具体细节,而不变的是执行的步骤和部分步骤中的内容。

在该炒菜实例中整个炒菜的流程是不变的,该流程中的一些步骤也是不变的。变化的就是报菜名方法中所报的菜名不同,然后是所炒的菜不同,一个炒的是土豆丝一个炒的是苦瓜,最后是加的调料不同。这样一分析,我们可以将不变的方法放到父类中,将炒菜这个不变的步骤封装成“模板方法”,具体不变的某些步骤(比如放油等)可以放在延展中实现。该部分的代码结构些微的有些复杂,所以我们会给出相应的类图。

1.重构后的类图如下(使用了“模板方法模式”)

首先我们会给出重构后的类图,使用“模板方法模式”重构后的类图如下所示。 FryVegetablesType是我们创建的炒菜协议,其中定义了“醋溜土豆丝”和“清炒苦瓜”所有的方法,不过我们对两者不同的方法进行了重新命名,让其统一。因为两者不同的方法所实现的东西大体一致,比如之前清炒苦瓜中的放苦瓜的方法putBitterGourd(),我们重命名成了“放蔬菜”的putVegetables()方法。putVegetables()方法用于“醋溜土豆丝”中也是可以的,因为putVegetables()在“清炒苦瓜”中放的是苦瓜,在炒土豆丝中放的是土豆丝。

在FryVegetablesType协议的延展中,我们给出了相同的默认实现,比如模板方法(fry())、放油(putSomeOil())、放葱花(putSomeGreenOnion())、出锅(outOfThePan())等方法。在炒这两个菜时延展中的方法是不变的。而我们炒土豆丝和炒苦瓜中实现的方法是两者不同的地方,类图如下:

2.炒菜接口与接口延展代码实现

根据上述的类图,我们可以给出炒菜接口以及接口延展的代码实现。接下来要做的事情就是将不变的部分提取到接口和接口的延展中,下方就是我们提取的炒菜的接口FryVegetablesType以及该接口对应的延展。FryVegetablesType协议中给出了模板方法fry(),以及炒菜的步骤(也就是炒菜的算法)。在该接口的延展中,模板方法fry()的默认实现调用和这些步骤,并且给出了一些不变的步骤的实现。具体代码如下所示:

3.“醋溜土豆丝”和“清炒苦瓜”的具体实现

下方代码段是醋溜土豆丝和清炒苦瓜在模板方法模式中的代码实现。从下方代码我们不难看出,两者都遵循了FryVegetablesType协议,并且拥有该协议的默认扩展。我们知道默认扩展中的代码类似于抽象类的默认实现,为子类所共有,所以下方两个类只给出了不同的步骤。比如在醋溜土豆丝中放的作料是盐和醋,而在清炒苦瓜中放的作料是盐。当然两个子类中其他实现的两个方法也是不同之处。无论子类怎么给出默认实现的步骤,我们在默认延展中给出的模板方法是不变的,也就是炒菜的具体步骤是不变的。这就是模板方法模式,模板方法不关心每个步骤的具体细节,只关心步骤执行的顺序,这就是所谓的模板方法是对算法的封装,而不是对具体计算细节的封装。

使用模板方法的一个显而易见的好处就是减少了代码冗余,将变化的部分与不变的部分进行了分离。在该示例中就是将不变的部分放在了协议的默认延展中,将变化的部分放在了子类中。这就是“模板方法模式”。

4、“模板方法模式”的测试用例

接下来我们要对上述的示例进行测试,下方就是我们模板方法的测试用例,其实下方的测试用例与之前没有使用模板方法时的测试用例类似,只是炒菜调用的方法有所不同。虽然调用的方法有些差异,此处的差异仅仅是函数名称的差异,该函数所做的事情没有变化。下方就是我们重构后的代码的测试用例以及运行结果。从结果中看出,与我们之前没有使用模板方法的测试用例的输出结果一致。这就是我们之前在“重构”系列博客中经常提到的改变代码内部的结构,而不改变代码对外调用的接口。

本篇博客与之前我们类重构中的“构建模板方法”的部分较为类似,都是介绍的模板方法模式。而在前面我们是从重构的角度来使用模板方法模式的,而今天的博客的主题不是重构而是我们的“模板方法模式”。由于篇幅有限,我们的今天的博客就先到这儿,后面还会继续更新其他Swift版的设计模式。

今天博客中的代码在github上的分享地址为:https://github.com/lizelu/DesignPatterns-Swift

设计模式(九): 从醋溜土豆丝和清炒苦瓜中来学习"模板方法模式"(Template Method Pattern)的更多相关文章

  1. 乐在其中设计模式(C#) - 模板方法模式(Template Method Pattern)

    原文:乐在其中设计模式(C#) - 模板方法模式(Template Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 模板方法模式(Template Method ...

  2. 设计模式 - 模板方法模式(template method pattern) JFrame 具体解释

    模板方法模式(template method pattern) JFrame 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考模板方法模式(templ ...

  3. 【java设计模式】【行为模式Behavioral Pattern】模板方法模式Template Method Pattern

    package com.tn.pattern; public class Client { public static void main(String[] args) { AbstractClass ...

  4. 设计模式 - 模板方法模式(template method pattern) 排序(sort) 具体解释

    模板方法模式(template method pattern) 排序(sort) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考模板方法模式(tem ...

  5. 设计模式 - 模板方法模式(template method pattern) 具体解释

    模板方法模式(template method pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 模板方法模式(template metho ...

  6. 二十四种设计模式:模板方法模式(Template Method Pattern)

    模板方法模式(Template Method Pattern) 介绍定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.Template Method使得子类可以不改变一个算法的结构即可重定义该算法 ...

  7. 设计模式 ( 十九 ) 模板方法模式Template method(类行为型)

      设计模式 ( 十九 ) 模板方法模式Template method(类行为型) 1.概述 在面向对象开发过程中,通常我们会遇到这样的一个问题:我们知道一个算法所需的关键步骤,并确定了这些步骤的执行 ...

  8. 模板方法模式 Template method 行为型 设计模式(二十六)

    模板方法模式 Template method 上图为网上百度的一份简历模板截图   相信大家都有求职的经历,那么必然需要简历,写简历的时候,很可能你会网上检索一份简历模板,使用此模板的格式,然后替换为 ...

  9. java设计模式 模板方法模式Template Method

    设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性.毫无疑问,设计模式于己 ...

随机推荐

  1. c#与java的区别

    经常有人问这种问题,用了些时间java之后,发现这俩玩意除了一小部分壳子长的还有能稍微凑合上,基本上没什么相似之处,可以说也就是马甲层面上的相似吧,还是比较短的马甲... 一般C#多用于业务系统的开发 ...

  2. 从中间件的历史来看移动App开发的未来

    在移动开发领域我们发现一个很奇怪的现象:普通菜鸟新手经过3个月的培训就可以拿到 8K 甚至上万的工作:在北京稍微有点工作经验的 iOS 开发,就要求 2 万一个月的工资.不知道大家是否想过:移动应用开 ...

  3. 轻量级“集合”迭代器-Generator

    Generator是PHP 5.5加入的新语言特性.但是,它似乎并没有被很多PHP开发者广泛采用.因此,在我们了解PHP 7对Generator的改进之前,我们先通过一个简单却显而易见的例子来了解下G ...

  4. 【Win 10 应用开发】应用预启动

    所谓预启动,其实你一看那名字就知道是啥意思了,这是直接译,也找不到比这个叫法更简练的词了.在系统资源允许的情况下(比如电池电量充足,有足够的内存空间),系统会把用户常用的应用程序在后台启动,但不会显示 ...

  5. [开发笔记] Graph Databases on developing

    TimeWall is a graph databases github It be used to apply mathematic model and social network with gr ...

  6. C#~异步编程再续~await与async引起的w3wp.exe崩溃-问题友好的解决

    返回目录 关于死锁的原因 理解该死锁的原因在于理解await 处理contexts的方式,默认的,当一个未完成的Task 被await的时候,当前的上下文将在该Task完成的时候重新获得并继续执行剩余 ...

  7. margin折叠-从子元素margin-top影响父元素引出的问题

    正在做一个手机端电商项目,顶部导航栈的布局是一个div包含一个子div,如果给在正常文档流中的子div一个垂直margin-top,神奇的现象出现了,两父子元素的边距没变,但父div跟着一起往下走了! ...

  8. 【JQ基础】数组

    each() 方法规定为每个匹配元素规定运行的函数.

  9. WINDOWS系统下MYSQL安装过程中的注意事项

    1.首先MySQL的安装方式有两种:一种是MSI安装方式,很简单就像安装Windows软件一样.另外一种就是ZIP安装方式.这种相对而言比较麻烦.新手推荐MSI安装方式. 安装方式有以下两种: MSI ...

  10. 在Mac OS X上安装ASP.NET 5(译文)

    ASP.NET 5 运行在包括OS X的可用于多个平台的.NET Execution Environment(DNX)上.本文介绍如何在OS X上通过HomeBrew安装DNX和ASP.NET 5. ...