• 泡茶?泡咖啡?

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

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

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

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

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

  如果我们用两个类去描述这两个过程,很明显会有很多重复的代码(例如 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. Linux下如何修改用户默认目录

      Linux下默认的用户目录一般为/home/xxx(root用户除外),有些时候我们可能需要修改这个目录,下面我就给大家分享2中修改的方法 工具/原料 Linux操作系统 方法/步骤 1 1.切换 ...

  2. 用配置文件方式启动mongodb集群

  3. 51nod 1693 水群

    基准时间限制:0.4 秒 空间限制:524288 KB 分值: 160 难度:6级算法题  收藏  关注 总所周知,水群是一件很浪费时间的事,但是其实在水群这件事中,也可以找到一些有意思的东西. 比如 ...

  4. Array - Merge Sorted Array

    /** * 将nums2中的值合并入nums1,使其仍然有序 * 可以任务nums1的长度>=m+n * @param nums1 已排序数组 * @param m nums1数组已初始化的数目 ...

  5. 三、npm start报错:./node_modules/history/esm/history.js解决办法

    package.json中的roadhog换为:'^2.5.0-beta.4',删除node_modules文件夹,在执行npm install,npm start.

  6. python基础一 day15 面试题

    # def demo():# for i in range(4):# yield i## g=demo()## g1=(i for i in g)# g2=(i for i in g1)## prin ...

  7. Cenos7—安装

    1. 进入安装界面 2. 选择语言 3. 进行分区 4. 设置root密码

  8. iOS 导航栏遮挡问题 --- iOS开发系列 ---项目中成长的知识七

    不知大家有没有遇见过自己写的tableview被导航栏遮挡住的问题,反正我是遇见过! 因为在ios7以后所有的UIViewController创建后默认就是full Screen的,因此如果带导航栏的 ...

  9. cocos2dx 3.x c++代码打包给lua调用过程(mac)

    下载cocos2dx 框架,在应用程序->cocos->framework->cocos2d-x-3.x->tools->tolua目录下,一个ini文件对应一个py文件 ...

  10. Chunky Monkey-freecodecamp算法题目

    Chunky Monkey(猴子吃香蕉, 分割数组) 要求 把一个数组arr按照指定的数组大小size分割成若干个数组块. 思路 利用size值和while语句确定切割数组的次数(定义temp将siz ...