模板设计模式主要来源于生活中有一些事情是有模板可以遵循的。举两个生活中的例子,如泡茶和泡咖啡,看一看。

  泡茶有以下四个步骤:  1, 烧开水;  2 把茶放到水杯中; 3,倒入开水; 4, 加糖。

  泡咖啡也同样有以下四个步骤: 1, 烧开水;  2 把咖啡放到水杯中; 3,倒入开水; 4, 加入糖和牛奶。

  这时,可以清楚地发现,无论是泡茶还是泡咖啡,它们的步骤几乎是相同的:1,开水, 2 放入水杯,3 倒入开水,4 加调味剂。只有具体到泡某种饮料时,它们有些步骤才不同,泡茶肯定是要把茶放到水杯中,而泡咖啡是把咖啡放到水杯中。这时我们就可以把相同的步骤提取出来,生成一个模版,进行共用,而到具体的内容时,它们再有具本的实现。 具体到代码时,模版就可以用抽象类实现,具体的内容可以到它的子类中实现。

  现在用抽象类把模版代码实现一下,

// 抽象基类,为所有的子类提供一个模版
public abstract class Beverage {

    // 具体的模板方法, 要用final关键字进行修饰,避免子类进行修改
    public final void prepareBeverageTemplate() {
        // 1, 烧开水
        boilWater();

        // 2, 放到杯中
        putIntoCup();

        // 加入开水
        addHotWater();

        // 加入调味应有剂
        addCondiments();
    }

    private void boilWater() {
        System.out.println("烧开水");
    }

    protected abstract void putIntoCup();

    private void addHotWater() {
        System.out.println("加水");
    }
    protected abstract void addCondiments();

}

  这里可以看到,在模板中,我们实现了两个方法 boilWater 和 addHotWater,因为这两个方法,对于泡任何饮料来说,都是相同的。另外两个方法则是抽象方法,因为只有到具体泡什么饮料时,这两个方法,才能具体实现,在这里我们并不知道泡茶还是咖啡,因而也就无法确定放入哪种饮料。

  抽象方法的实现要到子类中去, 声明咖啡子类和茶子类实现这两个方法

public class Coffee extends Beverage {

    @Override
    protected void putIntoCup() {
        System.out.println("把咖啡放到水杯中");
    }

    @Override
    protected void addCondiments() {
        System.out.println("加入糖和牛奶");
    }
}
public class Tea extends Beverage {

    @Override
    protected void putIntoCup() {
        System.out.println("把咖啡放到水杯中");
    }

    @Override
    protected void addCondiments() {
        System.out.println("加入糖和牛奶");
    }
}

  现在建立一个测试类Test 来使用一下模版模式

public class Test {

    public static void main(String[] args) {

        // 咖啡制作
        Beverage coffee = new Coffee();
        coffee.prepareBeverageTemplate();  // 调用模版
        System.out.println("\n***********************\n");
        // 茶制作
        Beverage tea = new Tea();
        tea.prepareBeverageTemplate(); // 调用模版
} }

  其实第4个步骤 加调味料不是必须的, 因为有些人喝茶或咖啡是不加调料的,那么怎么让我们程序更加通用化或者更加体现个性化需求?那就要提供一个钩子函数,具体到每个场景,使用不同的钩子函数。这时我们要把 addCondiments 方法放到一个if 函数进行调用, 而if 条件就是我们的钩子函数的调用。

  prepareBeverageTemplate 方法中的代码修改如下

if (isCustomered()) {
    // 加入调味应有剂
    addCondiments();
}
        

  新增 isCustomered 方法

    // 钩子函数,是否需要定置
    protected boolean isCustomered() {

        return true;
    }

  这时只要在子类中override这个钩子函数,就可以实现个性化需求,比如在茶中,复写这个方法

public class Tea extends Beverage {

    @Override
    protected void putIntoCup() {
        System.out.println("把咖啡放到水杯中");
    }

    @Override
    protected void addCondiments() {
        System.out.println("加入糖和牛奶");
    }

    @Override
    protected boolean isCustomered() {
        return false;
    }
}

  这时运行Test, 你就可以去掉加调味料这个步骤

Java 设计模式 ------ 模板设计模式的更多相关文章

  1. Java设计模式——模板设计模式

    模板设计模式 1.模板模式简介 模板模式(Template ):模板方法模式是类的行为模式.准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑 ...

  2. Java中的模板设计模式,太实用了!

    顾名思义,模板设计模式就是将许多公用的常用的代码封装成一个模板,我们只需要实现不同的业务需求的代码,然后和模板组合在一起,那么就得到完整的逻辑. 在我们的日常开发中,常用的模板模式有两种实现方式:继承 ...

  3. 【设计模式】Java设计模式 - 模板模式

    Java设计模式 - 模板模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...

  4. JAVA设计模式:模板设计模式

    1.模板设计模式,是为了体现继承的作用.它主要的作用就是在类中定义一些公共的方法和标准,而其具体的实现则叫给其子类来根据子类具体的行为来实现:因为模板设计模式中必经还有一些自己的方法不是抽象的方法,只 ...

  5. java模板设计模式

    1.概述 模板设计模式定义:定义一个操作中的算法骨架,将步骤延迟到子类中. 模板设计模式是一种行为设计模式,一般是准备一个抽象类,将部分逻辑以具体方法或者具体的构造函数实现,然后声明一些抽象方法,这样 ...

  6. Template Method 模板设计模式

    什么是模板设计模式 对于不了解的模板设计模式的来说,可以认为如同古代的造纸术一样,纸所以成型,取决于用了模板的形状,形状又由镂空的木板组成,而你想要造什么纸,又取决于你使用什么材料. 上面提到了两个关 ...

  7. Java进阶篇 设计模式之十四 ----- 总结篇

    前言 本篇是讲述之前学习设计模式的一个总结篇,其目的是为了对这些设计模式的进行一个提炼总结,能够通过查看看此篇就可以理解一些设计模式的核心思想. 设计模式简介 什么是设计模式 设计模式是一套被反复使用 ...

  8. Java进阶篇设计模式之一 ----- 单例模式

    前言 在刚学编程没多久就听说过设计模式的大名,不过由于当时还是个彻彻底底的菜鸟,并没有去触碰.直到在开始工作中对简单的业务代码较为熟悉之后,才正式的接触设计模式.当时最早接触的设计模式是工厂模式,不过 ...

  9. java之模板方法设计模式

    抽象类体现的就是一种模板模式的设计.抽象类作为多个子类的通用模板.子类在抽象类的基础上进行扩张和改造,但子类总体上会保留抽象类的行为方式. 解决的问题: 当功能内部一部分实现是确定的,一部分实现是不确 ...

随机推荐

  1. Linux内存管理 一个进程究竟占用多少空间?-VSS/RSS/PSS/USS

    关键词:VSS.RSS.PSS.USS._mapcount.pte_present.mem_size_stats. 在Linux里面,一个进程占用的内存有不同种说法,可以是VSS/RSS/PSS/US ...

  2. OPPO Developers Conference(2018.12.26)

    时间:2018.12.26地点:北京国家会议中心

  3. [Spark][Python][DataFrame][Write]DataFrame写入的例子

    [Spark][Python][DataFrame][Write]DataFrame写入的例子 $ hdfs dfs -cat people.json {"name":" ...

  4. flask实现子域名

    什么是子域名? 子域名,类似于xxx.douban.com的形式,如book.douban.com,music.douban.com,movie.douban.com等 用flask怎么实现子域名? ...

  5. c++继承实例

    #include <iostream> #include <vector> #include <string> using namespace std; class ...

  6. Linux—CentOS7下python开发环境配置

    CentOS7下python开发环境配置 上一篇博客讲了如何在Centos7下安装python3(https://www.cnblogs.com/zivli/p/9937608.html),这一次配置 ...

  7. 关于always块内for循环的执行方式

    //该模块主要用来说明for结构在时序逻辑中的执行方式 :] eq_dly ); integer i; 'b1; always @(posedge clk_1 or negedge nrst) beg ...

  8. C#使用OneNote的图片文字识别功能(OCR)

    http://www.cnblogs.com/Charltsing/p/OneNoteOCR.html 有需要技术咨询的,联系QQ564955427 前段时间有人问我能不能通过OneNote扫描图片, ...

  9. Python云端系统开发入门 pycharm代码

    html <!DOCTYPE html><html><head> <meta charset="UTF-8"> <title& ...

  10. anaconda安装win10

    注意事项: 1.下载安装,双选勾勾 2.安装python3.5的版本 conda create -n tensorflow python=3.5 3.激活环境activate tensorflow 4 ...