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

    前面的话   CSS视觉格式化这个词可能比较陌生,但说起盒模型可能就恍然大悟了.实际上,盒模型只是CSS视觉格式化的一部分.视觉格式化分为块级和行内两种处理方式.理解视觉格式化,可以确定得到的效果是应 ...

  2. [WCF]缺少一行代码引发的血案

    这是今天作项目支持的发现的一个关于WCF的问题,虽然最终我只是添加了一行代码就解决了这个问题,但是整个纠错过程是痛苦的,甚至最终发现这个问题都具有偶然性.具体来说,这是一个关于如何自动为服务接口(契约 ...

  3. 了不起的 nodejs-TwitterWeb 案例 bug 解决

    了不起的nodejs算是一本不错的入门书,不过书中个别案例存在bug,按照书中源码无法做出和书中相同效果,原本兴奋的心情掺杂着些许失落. 现在我们看一下第七章HTTP,一个Twitter Web客户端 ...

  4. Android Button的基本使用

    title: Android Button的基本使用 tags: Button,按钮 --- Button介绍: Button(按钮)继承自TextView,在Android开发中,Button是常用 ...

  5. ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存

    ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存 part 1:给我点时间,允许我感慨一下2016年 正好有时间,总结一下最近使用的一些技术,也算是为2016年画上一个完 ...

  6. Windos环境用Nginx配置反向代理和负载均衡

    Windos环境用Nginx配置反向代理和负载均衡 引言:在前后端分离架构下,难免会遇到跨域问题.目前的解决方案大致有JSONP,反向代理,CORS这三种方式.JSONP兼容性良好,最大的缺点是只支持 ...

  7. Cesium简介以及离线部署运行

    Cesium简介 cesium是国外一个基于JavaScript编写的使用WebGL的地图引擎,一款开源3DGIS的js库.cesium支持3D,2D,2.5D形式的地图展示,可以自行绘制图形,高亮区 ...

  8. 记:MySQL 5.7.3.0 安装 全程截图

    前言: 下一个班快讲MySQL数据库了,正好把服务器里面的MySQL卸了重装了一下. 截个图,作为笔记.也正好留给需要的朋友们. 目录: 下载软件 运行安装程序 安装程序欢迎界面 许可协议 查找更新 ...

  9. win10电脑优化

    Windows10必做的优化 --道心 关闭服务 右键点击"此电脑",选择"管理",进入"计算机管理"窗口. 在左侧的菜单选择"服 ...

  10. 二次剩余、三次剩余、k次剩余

    今天研究了一下这块内容...首先是板子 #include <iostream> #include <stdio.h> #include <math.h> #incl ...