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

  泡茶有以下四个步骤:  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. FineUIMvc v1.4.0 发布了(ASP.NET MVC控件库)!

    FineUIMvc v1.4.0 已经于 2017-06-30 发布,FineUIMvc 是基于 jQuery 的专业 ASP.NET MVC 控件库,是我们的新产品.由于和 FineUI(专业版)共 ...

  2. Spring Boot WebSocket从入门到放弃

    在构建Spring boot项目时已经提供webSocket依赖的勾选.webSocket是TCP之上的一个非常薄的轻量级层 ,webSocket主要的应用场景离不开即时通讯与消息推送,但只要应用程序 ...

  3. [C#] LINQ之LookUp

    声明:本文为www.cnc6.cn原创,转载时请注明出处,谢谢! 本文作者文采欠佳,文字表达等方面不是很好,但实际的代码例子是非常实用的,请作参考. 一.先准备要使用的类: 1.Person类: cl ...

  4. React 系列 - 写出优雅的路由

    前言 自前端框架风靡以来,路由一词在前端的热度与日俱增,他是几乎所有前端框架的核心功能点.不同于后端,前端的路由往往需要表达更多的业务功能,例如与菜单耦合.与标题耦合.与"面包屑" ...

  5. vue2.0之axios使用详解

    axios 基于 Promise 的 HTTP 请求客户端,可同时在浏览器和 node.js 中使用 功能特性 在浏览器中发送 XMLHttpRequests 请求 在 node.js 中发送 htt ...

  6. 抓包工具Charles的使用心得

    简介 Charles其实是一款代理服务器,通过成为电脑或者浏览器的代理,然后截取请求和请求结果达到分析抓包的目的.该软件是用Java写的,能够在Windows,Mac,Linux上使用.开发iOS都在 ...

  7. Leetcode 26. Remove Duplicates from Sorted Array (easy)

    Given a sorted array, remove the duplicates in-place such that each element appear only once and ret ...

  8. codeforces#1090 D. New Year and the Permutation Concatenation(打表找规律)

    题意:给出一个n,生成n的所有全排列,将他们按顺序前后拼接在一起组成一个新的序列,问有多少个长度为n的连续的子序列和为(n+1)*n/2 题解:由于只有一个输入,第一感觉就是打表找规律,虽然表打出来了 ...

  9. C++ string中的find()函数

    1.string中find()返回值是字母在母串中的位置(下标记录),如果没有找到,那么会返回一个特别的标记npos.(返回值可以看成是一个int型的数) #include<cstring> ...

  10. [2019BUAA软工助教]答黄杉同学

    [2019BUAA软工助教]答黄杉同学 一.答黄杉同学 011-黄衫博客 我当然不否认软件工程的各种博客是有一定作用的,但是相信大多数人对诸如例会博客并没有什么热情(不过似乎也没有什么其他方法保证团队 ...