设计模式(二十二)模板方法模式 Template
- 泡茶?泡咖啡?
我们用泡茶和泡咖啡两种行为来引入这一设计模式。
思考一下“泡茶”的过程:
煮水 -> 用沸水泡茶叶 -> 把茶倒进杯子 -> 放点柠檬之类的佐料。
然后再看一下“泡咖啡”的过程:
煮水 -> 用沸水泡咖啡 -> 把咖啡倒进杯子 -> 加牛奶和糖。
如果我们用两个类去描述这两个过程,很明显会有很多重复的代码(例如 Step1 煮水,Step3 倒进杯子),也有很多相似的代码(Step2 冲泡,Step4 加佐料)。
将冲泡的过程看做是一个算法,那么这个算法的主架构是一致的:
煮水 -> 用沸水泡东西 -> 将泡完的东西倒进杯子 -> 加佐料。
将主过程抽象出来,至于泡什么东西,加什么佐料,就交给子类去实现,这就是模板方法模式。
- 模板方法模式:
在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
- UML:

除了上述的四个步骤,这里加了个新的方法:customerWantsCondiments(),因为加佐料这个步骤不是必须的。
- 模板方法的组成:
从上面 UML 图,我们能够发现,在抽象类 BeverageDrive 中,一共存在4类方法:
- 模板方法:prepareRecipe(),这是算法的主体,在方法内部会调用其他的方法,一般来说是 public final 的。
- 抽象方法:brew() & addCondiments(),是算法步骤的“个性”,在 BeverageDrive 中声明为 protected abstract,由子类去实现。
- 具体方法:boilWater() & pourInCup(),是算法步骤的“共性”,一般是 private 的。
- 钩子方法:customerWantsCondiments,具有空的或是默认的实现。钩子的存在,可以让子类有能力对算法的不同点进行挂钩,选择权在子类手上,一般是 protected 的。
- 代码:
public abstract class BeverageDrive {
// Template method
public final void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}
// Abstract method
protected abstract void brew();
protected abstract void addCondiments();
// Concrete method
private void boilWater() {
System.out.println("Boiling water");
}
private void pourInCup() {
System.out.println("Pouring into cup");
}
// Hook method
protected boolean customerWantsCondiments() {
return true;
}
}
public final class CoffeeBeverage extends BeverageDrive {
@Override
public void brew() {
System.out.println("Dripping coffee through filter");
}
@Override
public void addCondiments() {
System.out.println("Adding sugar and milk");
}
@Override
public boolean customerWantsCondiments() {
return false;
}
}
public final class TeaBeverage extends BeverageDrive {
@Override
public void brew() {
System.out.println("Steeping the tea");
}
@Override
public void addCondiments() {
System.out.println("Adding lemon");
}
}
- 好莱坞原则:
好莱坞在寻找演员的时候有一个著名的原则:别打电话给我们,我们会打电话给你。
这一点在 OO 设计上,被翻译为:别调用我,我会调用你。
在好莱坞,演员属于低层组件,电影公司属于高层组件。每当电影公司需要演员的时候,都是电影公司打电话通知演员来面试。
换句话说:高层组件对待低层组件的方式是:别调用我,我会调用你。
当我们设计模板方法模式的时候,要时刻记得,让父类去调用子类,不要让子类调用父类方法。
下面看一个不太好的设计:
public abstract class BadBehaviorBeverageDrive {
protected void boilWater() {
System.out.println("Boiling water");
}
protected void pourInCup() {
System.out.println("Pouring into cup");
}
protected boolean customerWantsCondiments() {
return true;
}
}
public final class BadBehaviorTeaBeverage extends BadBehaviorBeverageDrive {
public final void prepareRecipe() {
super.boilWater();
steepTeaBags();
super.pourInCup();
if (super.customerWantsCondiments()) {
addLemon();
}
}
private void steepTeaBags() {
System.out.println("Steeping the tea");
}
private void addLemon() {
System.out.println("Adding lemon");
}
}
这个设计,一定意义上来说,达到了代码重用的功能,但是违反了好莱坞原则,不能算是一个合格的设计。
设计模式(二十二)模板方法模式 Template的更多相关文章
- 设计模式 ( 十九 ) 模板方法模式Template method(类行为型)
设计模式 ( 十九 ) 模板方法模式Template method(类行为型) 1.概述 在面向对象开发过程中,通常我们会遇到这样的一个问题:我们知道一个算法所需的关键步骤,并确定了这些步骤的执行 ...
- C#设计模式之十四模板方法模式(Template Method)【行为型】
一.引言 “结构型”的设计模式已经写完了,从今天我们开始讲“行为型”设计模式.现在我们开始讲[行为型]设计模式的第一个模式,该模式是[模板方法],英文名称是:Template Method Patte ...
- 模板方法模式 Template method 行为型 设计模式(二十六)
模板方法模式 Template method 上图为网上百度的一份简历模板截图 相信大家都有求职的经历,那么必然需要简历,写简历的时候,很可能你会网上检索一份简历模板,使用此模板的格式,然后替换为 ...
- 二十四种设计模式:模板方法模式(Template Method Pattern)
模板方法模式(Template Method Pattern) 介绍定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.Template Method使得子类可以不改变一个算法的结构即可重定义该算法 ...
- Java设计模式(十二) 策略模式
原创文章,同步发自作者个人博客,http://www.jasongj.com/design_pattern/strategy/ 策略模式介绍 策略模式定义 策略模式(Strategy Pattern) ...
- 备忘录模式 Memento 快照模式 标记Token模式 行为型 设计模式(二十二)
备忘录模式 Memento 沿着脚印,走过你来时的路,回到原点. 苦海翻起爱恨 在世间难逃避命运 相亲竟不可接近 或我应该相信是缘份 一首<一生所爱>触动了多少 ...
- 桥接模式 桥梁模式 bridge 结构型 设计模式(十二)
桥接模式Bridge Bridge 意为桥梁,桥接模式的作用就像桥梁一样,用于把两件事物连接起来 意图 将抽象部分与他的实现部分进行分离,使得他们都可以独立的发展. 意图解析 依赖倒置原 ...
- Java 设计模式系列(二十)状态模式
Java 设计模式系列(二十)状态模式 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式.状态模式允许一个对象在其内部状态改变的时候改 ...
- 小菜学习设计模式(一)—模板方法(Template)模式
前言 设计模式目录: 小菜学习设计模式(一)—模板方法(Template)模式 小菜学习设计模式(二)—单例(Singleton)模式 小菜学习设计模式(三)—工厂方法(Factory Method) ...
- 乐在其中设计模式(C#) - 模板方法模式(Template Method Pattern)
原文:乐在其中设计模式(C#) - 模板方法模式(Template Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 模板方法模式(Template Method ...
随机推荐
- NVM for Windows下载与安装
下载NVM for Windows https://github.com/coreybutler/nvm-windows/releases nvm-noinstall.zip: 这个是绿色免安装版本, ...
- javaSe-SimpleDateFormat
SimpleDateFormat呢是一种可以将字符串转为日期或者日期转换成字符串的功能强大的不得了的类: import java.text.ParseException;import java.tex ...
- POJ 3017 Cut the Sequence (单调队列优化DP)
题意: 给定含有n个元素的数列a,要求将其划分为若干个连续子序列,使得每个序列的元素之和小于等于m,问最小化所有序列中的最大元素之和为多少?(n<=105.例:n=8, m=17,8个数分别为2 ...
- 菜鸟的数据库实战-4-数据阅读器SqlDataReader
老铁们大家好啊,我是菜鸟思奎,今天我学习的是数据库和前端的连接用到的字符串,如果有什么纰漏希望大家在评论区指正.阿里嘎多. 我的环境是Visual Studio 2008 + Microsoft SQ ...
- uva10129 PlayOnWords(并查集,欧拉回路)
判断无向图是否存在欧拉回路,就是看度数为奇数的点有多少个,如果有两个,那么以那分别两个点为起点和终点,可以构造出一条欧拉回路,如果没有,就任意来,否则,欧拉回路不存在. 首先用并查集判断连通,然后统计 ...
- ubuntu下安装eclipse<转>
转载自http://my.oschina.net/u/1407116/blog/227084 http://my.oschina.net/u/1407116/blog/227087 一 JD ...
- java abstraction and encapsulation
How is Abstraction different from Encapsulation? Abstraction happens at class level design. It resul ...
- 已知一棵完全二叉树,求其节点的个数 要求:时间复杂度低于O(N),N为这棵树的节点个数
package my_basic.class_4; public class Code_08_CBTNode { // 完全二叉树的节点个数 复杂度低于O(N) public static class ...
- 【转】Matlab的regionprops详解
matlab函数_连通区域 1. matlab函数bwareaopen──删除小面积对象格式:BW2 = bwareaopen(BW,P,conn)作用:删除二值图像BW中面积小于P的对象,默认情况下 ...
- java版RSA工具类
/** * RSA算法加密/解密工具类 */ public class RSAUtils { private static final Logger LOGGER = LoggerFactory.ge ...