设计模式(二十二)模板方法模式 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 ...
随机推荐
- COGS 13. 运输问题4
★★☆ 输入文件:maxflowd.in 输出文件:maxflowd.out 简单对比时间限制:1 s 内存限制:128 MB [问题描述] 一个工厂每天生产若干商品,需运输到 ...
- 字符串转换JSON 的方法
function (sJSON) { if (window.JSON) { return window.JSON.parse(sJSON); } else { return eval('(' + sJ ...
- 【转】iOS学习笔记(十五)——数据库操作(SQLite)
SQLite (http://www.sqlite.org/docs.html) 是一个轻量级的关系数据库.SQLite最初的设计目标是用于嵌入式系统,它占用资源非常少,在嵌入式设备中,只需要几百K的 ...
- linux文件查找-find命令
find命令:用于在文件树中查找文件,并作出相应的处理 1.find命令的格式: find pathname -options [-print -exec -ok ...] {}\ 2.find命令的 ...
- 虚拟机设置NAT
需要开启虚拟机网络相关服务, 安装虚拟网卡, 还有必须安装 VMware Tools VMware虚拟机下实现NAT方式上网1. 把你的虚拟网卡VMnet8设置为自动获得IP.自动获得DNS服务器,启 ...
- Newtonsoft.Json初探
1.序列化 VehicleModelSearchingModel model = new VehicleModelSearchingModel() { brandId = , modelIds=&qu ...
- ANSI C 与 K&R C
C语言由Dennis M.Ritchie在1973年设计和实现.从那以后使用者逐渐增加.到1978年Ritchie和Bell实验室的另一位程序专家Kernighan合写了著名的<TheC Pro ...
- matplotlib绘图(三)
matplotlib中2D图形的绘制 直方图 直方图的参数只有一个x,不像条形图需要传入x,y 直方图作用:是统计x在某个区间上出现的次数 直方图是条形图的一种形式 hist()的参数: #bins ...
- 二分查找、upper_bound、lower_bound
整理及总结二分查找的判断和边界细节 修改版 package com.leej.binarysearch; import java.util.Arrays; /** * @author jerry * ...
- day 35 补充
MySQL数据库初识 MySQL数据库 本节目录 一 数据库概述 二 MySQL介绍 三 MySQL的下载安装.简单应用及目录介绍 四 root用户密码设置及忘记密码的解决方案 五 修改字符集 ...