模板方法模式(Head first 设计模式——7)
一、模板方法模式定义
模板方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
从定义中,应该可以看出一部分,为了更好理解,下面就直接上例子:
二、模板方法例子
在敲代码时,累了喝杯咖啡或者喝杯茶,会精神倍增。其实无论咖啡还是茶在冲的时间都是有讲究的。这个在本文不是重点。下面分别描述一下冲泡咖啡和冲泡茶的过程:

两种茶其分别的做法如下代码:
public class Coffee
{
public void PrepareRecipe()
{
//烧水
BoilWater();
//冲咖啡
BrewCoffeeGrinds();
//倒入茶杯中
PourInCup();
//加入糖和咖啡
AddSugarAndMilk();
}
public void BoilWater()
{
Console.WriteLine("烧水");
} public void BrewCoffeeGrinds()
{
Console.WriteLine("冲咖啡");
} public void PourInCup()
{
Console.WriteLine("倒入杯子中");
} public void AddSugarAndMilk()
{
Console.WriteLine("加糖和牛奶");
}
} public class Tea
{
public void PrepareRecipe()
{
//烧水
BoilWater();
//泡茶
SteepTeaBag();
//倒入茶杯中
PourInCup();
//加入柠檬
AddLemon();
}
public void BoilWater()
{
Console.WriteLine("烧水");
} public void SteepTeaBag()
{
Console.WriteLine("泡茶");
} public void PourInCup()
{
Console.WriteLine("倒入杯子中");
} public void AddLemon()
{
Console.WriteLine("加柠檬");
}
}
在面向对象语言中,是要讲求复用的,现在烧水和带入杯子的方法显然是重复的,这样就不符合对象村的村规——复用。
对比两种做法,都是需要四个步骤,能不能把相同的使用一个基类,不同的部分分别由自己的去实现。其类图如下

如果再细致观察的话,我们的冲咖啡和泡茶以及加入咖啡和牛奶都是属于差不多动作相同的。所以可以继续抽象,抽象后的方法大致如此:

其实得出的也就是我们的模板方法。下面来看看模板方法模式的类图:
三、模板方法类图

从类图可以看到我们把共用的方法放在抽象类中,用于复用。把不确定的方法,放入到具体类中,以便让具体类可以很好的构造自己的方法。除此之外,还有个重点是无论是构造好的方法也好,还是抽象的方法也好,都会被装入到一个TemplateMethod方法中。就像我们平时的做项目也是如此,大致的步骤需要:需求分析——>编码——>测试,这些最基本的过程。但是具体的每一步,可能都是不同的,但是做项目的过程的几个步骤是基本不变的,把步骤抽象成了模板,以后做项目的时间,都按这个步骤去做。这个就是我们的模板方法模式。到这里还是把我们的茶和咖啡沏好。
基类代码:
public abstract class CoffeeinBeverage1
{
public void BoilWater()
{
Console.WriteLine("烧水");
} public void PrepareRecipe()
{
BoilWater();
Brew();
PourInCup();
AddCondiments();
} public void PourInCup()
{
Console.WriteLine("倒入杯子中");
} public abstract void Brew(); public abstract void AddCondiments(); }
咖啡代码:
public class Coffee1 : CoffeeinBeverage1
{
public override void Brew()
{
Console.WriteLine("冲咖啡"); } public override void AddCondiments()
{
Console.WriteLine("加糖和牛奶");
}
茶代码:
public class Tea1 : CoffeeinBeverage1
{
public override void Brew()
{
Console.WriteLine("泡茶");
} public override void AddCondiments()
{
Console.WriteLine("加柠檬");
} }
四、模板方法注意的问题
在上面的茶水和咖啡中,现在是看起来能喝了,但是有个问题就是有些人喝咖啡喜欢不加任何调味料的。那么我们硬是给客人加,肯定是会生气的。为了满足这个要求,设计模式提供的有这个解决方案——使用钩子。具体什么是钩子,我们小的时间的课本上有个猴子捞月亮的图片:

每个猴子不仅会被其他猴子拉住,还会伸出一个手去拉其他猴子。但最后一个手是没有拉其他猴子了,但是还是要伸下去的,以防碰不到月亮。
同样不知道方法能不能用得到,但是有对应的方法,具体的什么时间用得到,什么时间用不到,根据条件来判断。
下面来看看钩子如何在模板方法模式中使用的:
基类代码:
public void PrepareRecipe()
{
BoilWater();
Brew();
PourInCup();
//有个判断方法来添加调料
if (WantCondiments())
{
AddCondiments();
}
}
/// <summary>
/// 加入一个方法,用来判断是否需要加调料
/// </summary>
/// <returns></returns>
public virtual bool WantCondiments()
{
return true;
}
在子类中,可以通过不同的方式类覆盖WantCondiment()方法。用来表示是否要加调料的标准,在此方法中注意必须加入virtual关键字,以便子类中使用override重写。下面看看咖啡中的方法:
public override bool WantCondiments()
{
return false;
}
下面是测试代码:
class Program
{
static void Main(string[] args)
{
CoffeeinBeverage1 coffeninBeverage = new Coffee1();
coffeninBeverage.PrepareRecipe();
Console.ReadKey();
}
}
输出结果:

发现已经去掉了调料。
五、模板方法模式和策略模式以及工厂方法的对比
在看模板方法的时间,很容易想到工厂方法。因为他们都是让具体的实现放在子类中,但是工厂方法主要是生产出产品,然后去应用产品。模板方法是在于依赖子类中的步骤中的其中几个步骤,具体的步骤已经在基类中写好了。
同样模板方法模式和策略模式都是封装算法。但是策略模式中的每个策略都是单独的一个类。可以随时去更改策略。模板方法模式虽然也是封装了算法,其实主要在于封装步骤,具体的实现是根据依靠各个子类。
除此之外,模板方法模式还涉及到一个好莱坞原则:
不要给我打电话,我会主动和你打电话。
在模板方法模式中扮演好莱坞的角色是抽象类,子类是演员的角色。
一般需要调用子类中的方法都已经在模板中定义好了,需要时,会主动联系各个步骤,最好在子类中不要去调用抽象类中的方法具体方法,以防止子类和父类的调用的凌乱。
六、总结和源码
本文主要先列出了模板方法模式的定义,然后通过例子来帮助理解模式,接着提出钩子在模板方法模式中的使用,最后简单对比了模板方法模式、策略模式以及工厂方法模式。
模板方法模式(Head first 设计模式——7)的更多相关文章
- 8.模板方法模式-[Head First 设计模式]
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. 要点: “模板方法”定义了算法的步骤,把这些步骤的实现延 ...
- java模式之-模板方法模式
模板方法模式是java设计模式常见的模式之一. <JAVA与模式>中写道: 模板方法模式是类的行为模式.准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法 ...
- 设计模式(九): 从醋溜土豆丝和清炒苦瓜中来学习"模板方法模式"(Template Method Pattern)
今天是五.四青年节,祝大家节日快乐.看着今天这标题就有食欲,夏天到了,醋溜土豆丝和清炒苦瓜适合夏天吃,好吃不上火.这两道菜大部分人都应该吃过,特别是醋溜土豆丝,作为“鲁菜”的代表作之一更是为大众所熟知 ...
- 设计模式(十四)模板方法模式(Template Pattern)
一.引言 提到模板,大家肯定不免想到生活中的“简历模板”.“论文模板”.“Word中模版文件”等,在现实生活中,模板的概念就是——有一个规定的格式,然后每个人都可以根据自己的需求或情况去更新它,例如简 ...
- C#设计模式-模板方法模式
提到模板,大家肯定不免想到生活中的“简历模板”.“论文模板”.“Word中模版文件”等,在现实生活中,模板的概念就是——有一个规定的格式,然后每个人都可以根据自己的需求或情况去更新它,例如简历模板,下 ...
- C#设计模式系列:模板方法模式(Template Method)
你去银行取款的时候,银行会给你一张取款单,这张取款单就是一个模板,它把公共的内容提取到模板中,只留下部分让用户来填写.在软件系统中,将多个类的共有内容提取到一个模板中的思想便是模板方法模式的思想. 模 ...
- java设计模式 模板方法模式Template Method
设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性.毫无疑问,设计模式于己 ...
- java设计模式之模板方法模式
模板方法模式 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中. 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤.通俗的说的就是有很多相同的步骤的,在某一些地方可能有一些差 ...
- JAVA 设计模式 模板方法模式
定义 模板方法模式 (Template Method) 定义了一个操作中的算法的骨架,而将部分步骤的实现在子类中完成. 模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 模 ...
- 深入浅出设计模式——模板方法模式(Template Method Pattern)
模式动机 模板方法模式是基于继承的代码复用基本技术,模板方法模式的结构和用法也是面向对象设计的核心之一.在模板方法模式中,可以将相同的代码放在父类中,而将不同的方法实现放在不同的子类中.在模板方法模式 ...
随机推荐
- cpuinfo详解
cat /proc/cpuinfo processor: 23:超线程技术的虚拟逻辑核第24个 ###一般看最后一个0...23 表示24线程 vendor_id: GenuineIntel:CP ...
- Cocos2dx 学习记录 [2] 关于混合和高亮一些知识点的体会
网上有一篇博客讲的是高亮的http://www.cnblogs.com/mrblue/p/3455775.html 就是这篇,尽管代码简单,但对于刚開始学习的人的我,看的还是有些吃力的,毕竟有些内容不 ...
- Linux安装Nginx1.7.4、php5.5.15和配置
Nginx是一个轻量级的高性能Webserver.反向代理server.邮件(IMAP/POP3/SMTP)server,是Igor Sysoev为俄罗斯訪问量第二的Rambler.ru网站开发,第一 ...
- 从gentoo回归Arch,上组图
Arch一直在我笔记本里边,只是玩gentoo时我不进Arch了,现在回归Arch,升级到了最新,用上了gentoo的最新的2.6.31内核(自己配置,无initrd),引导程序用的grub4dos: ...
- web实现QQ第三方登录 开放平台-web实现QQ第三方登录
应用场景 web应用通过QQ登录授权实现第三方登录. 操作步骤 1 注册成为QQ互联平台开发者,http://connect.qq.com/ 2 准备一个可访问的域名, ...
- Python练习笔记——斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一 ...
- android语音识别方法
http://www.apkbus.com/forum.php?mod=viewthread&tid=3473 android语音识别方法一:使用intent调用语音识别程序 1. 说明 以下 ...
- Concurrency Managed Workqueue(二)CMWQ概述
一.前言 一种新的机制出现的原因往往是为了解决实际的问题,虽然linux kernel中已经提供了workqueue的机制,那么为何还要引入cmwq呢?也就是说:旧的workqueue机制存在什么样的 ...
- mysql 再查询结果的基础上查询(子查询)
SELECT A.wx_name, A.wx_litpic, B . * FROM ( SELECT uid, COUNT( * ) AS daticishu FROM statements , ) ...
- 使用 docker 搭建 openvpn,创建、删除用户证书
我自己的配置,服务器:ubuntu16.04 + docker 17.12.0-ce:客户端:win10 + openvpn2.4.5 1 在dockerhub上搜索 openvpn,我是用的是 进去 ...