• 泡茶?泡咖啡?

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

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

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

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

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

  如果我们用两个类去描述这两个过程,很明显会有很多重复的代码(例如 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. Vijos P1243 生产产品 (单调队列优化DP)

    题意: 必须严格按顺序执行M个步骤来生产一个产品,每一个步骤都可以在N台机器中的任何一台完成.机器i完成第j个步骤的时间为T[i][j].把半成品从一台机器上搬到另一台机器上也需要一定的时间K.每台机 ...

  2. GPnP profile内容

    <?xml version="1.0" encoding="UTF-8"?>  <gpnp:GPnP-Profile Version=&quo ...

  3. JS实现全排列

    https://www.jb51.net/article/39291.htm JavaScript全排列的六种算法 具体实现 算法一:交换(递归) 复制代码代码如下: <html xmlns=& ...

  4. java基础—GUI编程(二)

    一.事件监听

  5. servlet实现简单的反向代理

    项目基于Spring 须要的依赖为: <dependency> <groupId>org.mitre.dsmiley.httpproxy</groupId> < ...

  6. linux 下使用 curl 访问带多参数,GET掉参数解决方案

    url 为 http://mywebsite.com/index.php?a=1&b=2&c=3 web形式下访问url地址,使用 $_GET是可以获取到所有的参数 curl  -s  ...

  7. SizeClass介绍

    随着iOS8系统的发布,一个全新的页面UI布局概念出现,这个新特性将颠覆包括iOS7及之前版本的UI布局方式,这个新特性就是Size Class.Size Class配合Auto Layout可以解决 ...

  8. js函数式编程(一)-纯函数

    我将写的第一个主题是js的函数式编程,这一系列都是mostly adequate guide这本书的读书总结.原书在gitbook上,有中文版.由于原作者性格活泼,书中夹杂很多俚语,并且行文洒脱.中文 ...

  9. I/O理解

    I/O是什么 我的理解I/O就是用于读写的一个流 官方解释:I/O(英语:Input/Output),即输入/输出,通常指数据在内部存储器和外部存储器或其他周边设备之间的输入和输出. node中的io ...

  10. cena 测评机下载地址

    以下是cane的下载地址,现在分享给你们,希望有所帮助 下载地址百度云:https://pan.baidu.com/s/1JBXiVSZy-jhIc0V-F2ESPA 密码:hgtk 点击下载即可. ...