模板方法模式的实现要素

  • 抽象基类

    • 提供基本的实现方法,具有共性的方法
    • 抽象方法,不知道具体实现的方法,由子类进行具体实现
    • 可选钩子函数,基类中提供默认或空实现
    • Template方法(final),将所有方法汇总而成的模板方法

    好莱坞原则:子类可以替换掉父类可变逻辑,但不能改变整体逻辑

  • 具体子类

    • 实现基类中的抽象方法,提供具体的,个性化的实现
    • 可选的覆盖钩子函数,个性化的影响局部行为
  • 总结

    • 准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性。最后将方法汇总构成一个不可改变的模板方法。

模板方法模式的适用场景

  • 算法或操作遵循相似的逻辑
  • 重构时(把相同的代码抽取到父类中)
  • 重要、复杂的算法,核心算法设计为模板算法

模板方法模式的优缺点

优点

  • 封装性好
  • 复用性好
  • 屏蔽细节
  • 便于维护

缺点

  • 由于java语言单继承的特性,一个类已经继承了某一个类,那么我们无法在使用继承的方式实现模板方法模式

模板方法模式的基本实现

饮料调制的小例子

  • 基本过程
咖啡
把水煮沸 把水煮沸
用沸水冲泡咖啡 用沸水浸泡茶叶
把咖啡倒进杯子 把咖啡倒进杯子
加糖和牛奶 加柠檬
  • 抽取相似过程
把水煮沸(boilWater)
泡饮料(brew)
把饮料倒进杯子(pourInCup)
加调味料(addCondiments)

RefreshBeverage抽象基类

package com.example.java_study.template_method;/*** @author xianping* @version 1.0* @classname RefreshBeverage[提神饮料]* @description 抽象基类,为所有子类提供算法框架* @date 2020/09/12 8:48*/
public abstract class RefreshBeverage {/** 制作饮料的模板方法* 封装了所有子类共同遵循的算法框架* @description [抽象基类定义了算法框架,final关键字禁止子类对算法框架做任何改变、阻止子类对父类方法复写]* @author xianping* @date 2020/9/12* @return void**/public final void prepareBeverageTemplate() {//步骤1:将水煮沸boilWater();//步骤2:泡制饮料brew();//步骤3:将饮料倒入杯中pourInCup();//步骤4:加入调味料addCondiMents();}/** @description 将水煮沸[公用方法,声明为private,减少子类复写工作量]* @author xianping* @date 2020/9/12* @return void**/private void boilWater() {System.out.println("将水煮沸");}/** @description 泡制饮料[需要子类进行实现的方法定义为abstract,具体实现由子类进行]* @author xianping* @date 2020/9/12* @return void**/abstract void brew();/** @description 将饮料倒入杯中[公用方法,声明为private,减少子类复写工作量]* @author xianping* @date 2020/9/12* @return void**/private void pourInCup() {System.out.println("将饮料倒入杯中");}/** @description 加入调味料[需要子类进行实现的方法定义为abstract,具体实现由子类进行]* @author xianping* @date 2020/9/12* @return void**/abstract void addCondiMents();
}

Coffee实现类

package com.example.java_study.template_method;/*** @author xianping* @version 1.0* @classname Coffee 具体子类、咖啡类* @description* @date 2020/09/12 9:10*/
public class Coffee extends RefreshBeverage {/** @description 将饮料倒入杯中* @author xianping* @date 2020/9/12* @return void**/@Overridevoid brew() {System.out.println("用沸水冲泡咖啡");}/** @description 加入调味料* @author xianping* @date 2020/9/12* @return void**/@Overridevoid addCondiMents() {System.out.println("加入糖和牛奶");}
}

Tea实现类

package com.example.java_study.template_method;/*** @author xianping* @version 1.0* @classname Coffee 具体子类、咖啡类* @description* @date 2020/09/12 9:10*/
public class Tea extends RefreshBeverage {/** @description 将饮料倒入杯中* @author xianping* @date 2020/9/12* @return void**/@Overridevoid brew() {System.out.println("用80度热水浸泡茶叶5分钟");}/** @description 加入调味料* @author xianping* @date 2020/9/12* @return void**/@Overridevoid addCondiMents() {System.out.println("加入柠檬");}
}

测试方法

package com.example.java_study.template_method;/*** @author xianping* @version 1.0* @classname RefreshBeverageTest* @description* @date 2020/09/12 9:14*/
public class RefreshBeverageTest {public static void main(String[] args) {//制作咖啡RefreshBeverage coffee = new Coffee();coffee.prepareBeverageTemplate();//制作茶RefreshBeverage tea = new Tea();tea.prepareBeverageTemplate();}
}

结果

将水煮沸
用沸水冲泡咖啡
将饮料倒入杯中
加入糖和牛奶
将水煮沸
用80度热水浸泡茶叶5分钟
将饮料倒入杯中
加入柠檬

钩子函数

  • 如果我们想制作一杯不加任何调料的饮料,那么现有的模板是无法满足的
  • 这时可以引入一个钩子函数,子类可选择重写父类钩子函数从而达到制作无任何调味料的饮料

RefreshBeverage抽象基类

package com.example.java_study.template_method;/*** @author xianping* @version 1.0* @classname RefreshBeverage[提神饮料]* @description 抽象基类,为所有子类提供算法框架* @date 2020/09/12 8:48*/
public abstract class RefreshBeverage {/** 制作饮料的模板方法* 封装了所有子类共同遵循的算法框架* @description [抽象基类定义了算法框架,final关键字禁止子类对算法框架做任何改变、阻止子类对父类方法复写]* @author xianping* @date 2020/9/12* @return void**/public final void prepareBeverageTemplate() {//步骤1:将水煮沸boilWater();//步骤2:泡制饮料brew();//步骤3:将饮料倒入杯中pourInCup();//步骤4:加入调味料if (isCustomerWantsCondiments()) {addCondiMents();}}/**Hook方法,钩子函数。提供一个默认实现或为空的实现,具体的子类可以自行决定是否挂钩以及如何挂钩* @description 询问用户是否加入调料[protected子类可以进行重写,非子类无法进行重写]* @author xianping* @date 2020/9/12* @return boolean**/protected boolean isCustomerWantsCondiments() {return true;}/** @description 将水煮沸[公用方法,声明为private,减少子类复写工作量]* @author xianping* @date 2020/9/12* @return void**/private void boilWater() {System.out.println("将水煮沸");}/** @description 泡制饮料[需要子类进行实现的方法定义为abstract,具体实现由子类进行]* @author xianping* @date 2020/9/12* @return void**/abstract void brew();/** @description 将饮料倒入杯中[公用方法,声明为private,减少子类复写工作量]* @author xianping* @date 2020/9/12* @return void**/private void pourInCup() {System.out.println("将饮料倒入杯中");}/** @description 加入调味料[需要子类进行实现的方法定义为abstract,具体实现由子类进行]* @author xianping* @date 2020/9/12* @return void**/abstract void addCondiMents();
}

Tea实现类

package com.example.java_study.template_method;/*** @author xianping* @version 1.0* @classname Coffee 具体子类、咖啡类* @description* @date 2020/09/12 9:10*/
public class Tea extends RefreshBeverage {/** @description 将饮料倒入杯中* @author xianping* @date 2020/9/12* @return void**/@Overridevoid brew() {System.out.println("用80度热水浸泡茶叶5分钟");}/** @description 加入调味料* @author xianping* @date 2020/9/12* @return void**/@Overridevoid addCondiMents() {System.out.println("加入柠檬");}/** @description 子类选择挂载钩子函数,通过重写的父类钩子函数,提供一个符合自己的实现* @author xianping* @date 2020/9/12* @return boolean**/@Overrideprotected boolean isCustomerWantsCondiments() {return false;}
}

RefreshBeverageTest

package com.example.java_study.template_method;/*** @author xianping* @version 1.0* @classname RefreshBeverageTest* @description* @date 2020/09/12 9:14*/
public class RefreshBeverageTest {public static void main(String[] args) {//制作茶RefreshBeverage tea = new Tea();tea.prepareBeverageTemplate();}
}

结果

将水煮沸
用80度热水浸泡茶叶5分钟
将饮料倒入杯中

设计模式-模板方法模式相关推荐

  1. 在一个程序设计里,不同的功能窗口有着相似的功能实现方式,可采用设计模式---模板方法模式

        前段时间学习了一些设计模式,最近在做项目的过程中恰巧用到了其中的一个--模板方法模式.这个模式在程序设计过程中可是为小编省去了不少的代码量呢.具体是怎样应用的呢?接下来小编为您分享. 前面博文 ...

  2. 『设计模式』瑞幸咖啡还是星巴克,一杯下午茶让我明白 设计模式--模板方法模式(Template Method Pattern)

    23种设计模式+额外常用设计模式汇总 (持续更新) 简介 Define the skeleton of an algorithm in an operation,deferring some step ...

  3. 『设计模式』设计模式--模板方法模式

    23种设计模式+额外常用设计模式汇总 (持续更新) 简介 Define the skeleton of an algorithm in an operation,deferring some step ...

  4. 行为型设计模式---模板方法模式

    设计模式 序号 内容 链接地址 1 设计模式七大原则 https://blog.csdn.net/qq_39668819/article/details/115390615 2 创建型设计模式–工厂模 ...

  5. Java设计模式-模板方法模式详解

    Java设计模式-模板方法模式 文章目录 Java设计模式-模板方法模式 0.前言 1.模板方法原理 2.模板方法模式中的角色 3.模板方法模式的UML类图 4.代码实现 5.编码测试 6.模板模式中 ...

  6. Java设计模式 - 模板方法模式

    Java设计模式 - 模板方法模式 定义一个算法的骨架,并将一些步骤通过子类表达. UML图示 要点 1. 定义一个算法的骨架 - 建立一个抽象类 2. 将一些步骤通过子类表达 - 子类继承抽象类 赋 ...

  7. linkin大话设计模式--模板方法模式

    linkin大话设计模式--模板方法模式 准备一个抽象类,将部分逻辑以具体方法的形式实现,然后申明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不 ...

  8. JAVA 设计模式 模板方法模式

    定义 模板方法模式 (Template Method) 定义了一个操作中的算法的骨架,而将部分步骤的实现在子类中完成. 模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 模 ...

  9. 模板设计模式_设计模式-模板方法模式

    一.模板方法模式的定义 在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板.它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行.这种类型的设计 ...

  10. 大话设计模式—模板方法模式

    在模板方法模式(TemplateMethod Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板.它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行.这种类型的设计模式属于 ...

最新文章

  1. 数据库内核月报 - 2017年12月
  2. 鼠标放在图片连接上面,预览图片
  3. Parallel并行计算合计数据时错误的原因和解决办法
  4. Struts1和Struts2的区别和对比
  5. asp.net mvc中ckeditor+ckfinder的配置方法
  6. 前端学习(1578):React简介
  7. Linux工作笔记-使用SCP文件协议(SSH协议22端口)使Windows与Linux互传文件
  8. Linux下监视NVIDIA的GPU使用情况
  9. python print不换行输出_python中print如何不换行输出
  10. hihoCoder - 1079 - 离散化 (线段树 + 离散化)
  11. 学好平面设计需要哪些技术功底?
  12. 新浪微博热门话题 (30 分)
  13. Trend趋势反垃圾邮件黑名单申诉方法
  14. ABBYY FineReader Engine OCR 软件开发工具包深度解析
  15. 转:红帽旗下Linux的版本说明RedHat、CentOS、Fedora、OEL等
  16. 苏州市区公积金与园区公积金新政策-乙类对比 (包括住房公积金)
  17. [交易日记]2016-11-24交易笔记
  18. Poi导入Excel校验表头
  19. 保姆级Windows下载安装PaddleGAN并使用教程
  20. java二叉树计算深度

热门文章

  1. RuntimeError: CUDA error: device-side assert triggered的解决
  2. Xiangqi UVa1589
  3. Latex中使用thebibliography环境时去除“参考文献”标题方法
  4. 数据链路层之以太网、MAC、MTU详解
  5. CHM格式的帮助文档制作与代码调用 Visual Studio C#
  6. python flag用法_Python之FLAGS用法
  7. 顾客价值理论(转载)
  8. Minecraft 我的世界 .minecraft下的各个文件夹的用处
  9. 第三届“传智杯”全国大学生IT技能大赛(初赛B组)题解
  10. 大话西游片尾曲-一生所爱(世界是巨大的枷锁,你不得不重复自己或是别人的生活)