• 泡茶?泡咖啡?

  我们用泡茶和泡咖啡两种行为来引入这一设计模式。

  思考一下“泡茶”的过程:

  煮水 -> 用沸水泡茶叶 -> 把茶倒进杯子 -> 放点柠檬之类的佐料。

  然后再看一下“泡咖啡”的过程:

  煮水 -> 用沸水泡咖啡 -> 把咖啡倒进杯子 -> 加牛奶和糖。

  如果我们用两个类去描述这两个过程,很明显会有很多重复的代码(例如 Step1 煮水,Step3 倒进杯子),也有很多相似的代码(Step2 冲泡,Step4 加佐料)。

  将冲泡的过程看做是一个算法,那么这个算法的主架构是一致的:

  煮水 -> 用沸水泡东西 -> 将泡完的东西倒进杯子 -> 加佐料。

  将主过程抽象出来,至于泡什么东西,加什么佐料,就交给子类去实现,这就是模板方法模式。

  • 模板方法模式:

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

  • UML:

  除了上述的四个步骤,这里加了个新的方法:customerWantsCondiments(),因为加佐料这个步骤不是必须的。

  • 模板方法的组成:

  从上面 UML 图,我们能够发现,在抽象类 BeverageDrive 中,一共存在4类方法:

  1. 模板方法:prepareRecipe(),这是算法的主体,在方法内部会调用其他的方法,一般来说是 public final 的。
  2. 抽象方法:brew() & addCondiments(),是算法步骤的“个性”,在 BeverageDrive 中声明为 protected abstract,由子类去实现。
  3. 具体方法:boilWater() & pourInCup(),是算法步骤的“共性”,一般是 private 的。
  4. 钩子方法: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的更多相关文章

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

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

  2. C#设计模式之十四模板方法模式(Template Method)【行为型】

    一.引言 “结构型”的设计模式已经写完了,从今天我们开始讲“行为型”设计模式.现在我们开始讲[行为型]设计模式的第一个模式,该模式是[模板方法],英文名称是:Template Method Patte ...

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

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

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

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

  5. Java设计模式(十二) 策略模式

    原创文章,同步发自作者个人博客,http://www.jasongj.com/design_pattern/strategy/ 策略模式介绍 策略模式定义 策略模式(Strategy Pattern) ...

  6. 备忘录模式 Memento 快照模式 标记Token模式 行为型 设计模式(二十二)

    备忘录模式 Memento   沿着脚印,走过你来时的路,回到原点.     苦海翻起爱恨   在世间难逃避命运   相亲竟不可接近   或我应该相信是缘份   一首<一生所爱>触动了多少 ...

  7. 桥接模式 桥梁模式 bridge 结构型 设计模式(十二)

      桥接模式Bridge   Bridge 意为桥梁,桥接模式的作用就像桥梁一样,用于把两件事物连接起来   意图 将抽象部分与他的实现部分进行分离,使得他们都可以独立的发展.  意图解析 依赖倒置原 ...

  8. Java 设计模式系列(二十)状态模式

    Java 设计模式系列(二十)状态模式 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式.状态模式允许一个对象在其内部状态改变的时候改 ...

  9. 小菜学习设计模式(一)—模板方法(Template)模式

    前言 设计模式目录: 小菜学习设计模式(一)—模板方法(Template)模式 小菜学习设计模式(二)—单例(Singleton)模式 小菜学习设计模式(三)—工厂方法(Factory Method) ...

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

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

随机推荐

  1. Integer的一个小问题

    看面试题的时候看到这道题: public class Demo { public static void main(String[] args) { Integer i1 = 128; Integer ...

  2. 利用jieba第三方库对文件进行关键字提取

    已经爬取到的斗破苍穹文本以TXT形式存储 代码 import jieba.analyse path = 'C:/Users/Administrator/Desktop/bishe/doupo.text ...

  3. 【转】IOS开发—IOS 8 中设置applicationIconBadgeNumber和消息推送

    在IOS7中设置applicationIconBadgeNumber不会有什么问题,但是直接在IOS8中设置applicationIconBadgeNumber会报错 因为在IOS8中要想设置appl ...

  4. 二、antd pro 删除eslint检测

    删除package.json 里 " pre-commit": "npm run lint-staged" 这个对象就可以.

  5. 《队长说得队》第八次团队作业Alpha冲刺

    项目 内容 这个作业属于哪个课程 >>2016级计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 >>实验十二 团队作业8:软件测试与ALPHA冲刺 团队名称 ...

  6. superset docker 部署

    公众号原文有更多效果图哦 一.使用自己的数据库 1. 拉取项目 // 创建目录用于存放项目 mkdir -p /mnt/superset cd /mnt/superset git clone http ...

  7. javaweb基础(18)_jsp属性范围

    所谓的属性范围就是一个属性设置之后,可以经过多少个其他页面后仍然可以访问的保存范围. 一.JSP属性范围 JSP中提供了四种属性范围,四种属性范围分别指以下四种: 当前页:一个属性只能在一个页面中取得 ...

  8. nodejs个人博客系统

    说明:本人目前还是一名C#程程序,在公司干过一年的前端(ps切图,html+css,js),二年的后台C#(b/s,c/s)的开发.因为想转型所以学习了nodejs这门感觉非常棒的一门语言.于是写了一 ...

  9. C#基于联通短信Sgip协议构建短信网关程序

    此软件基于中国联通Sgip协议程序接口,适合在中国联通申请了短信发送端口的公司使用.短信群发已经成为现在软件系统.网络营销等必不可少的应用工具.可应用在短信验证.信息群发.游戏虚拟商品购买.事件提醒. ...

  10. 解决 cocos2dx iOS/mac 设置纹理寻址模式后纹理变黑的问题

    sprite:getTexture():setTexParameters(gl.LINEAR,gl.LINEAR,gl.REPEAT,gl.REPEAT) 在安卓设备上,设置了纹理自定义寻址模式,纹理 ...