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

目录

一、豆浆制作问题

二、模板方法模式基本介绍

三、原理类图

四、模板方法模式解决豆浆制作问题

五、模板方法模式的钩子方法

六、模板方法模式在Spring框架应用的源码分析

七、注意事项和细节


一、豆浆制作问题

编写制作豆浆的程序,说明如下 :
1) 制作豆浆的流程 选材 ---> 添加配料 ---> 浸泡 ---> 放到豆浆机打碎
2) 通过添加不同的配料,可以制作出不同口味的豆浆
3) 选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的
4) 请使用 模板方法模式 完成 ( 说明:因为模板方法模式,比较简单, 很容易就 想到这个方案 ,因此就直接使用,不再使用传统的方案来引出模板方法模式 )

二、模板方法模式基本介绍

1) 模板方法模式( Template Method Pattern ),又叫模板模式 (Template Pattern) 在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。
2) 简单说, 模板方法模式 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤
3) 这种类型的设计模式属于行为型模式。

三、原理类图

对原理类图的说明-即(模板方法模式的角色及职责 )
1) AbstractClass 抽象类, 类中实现了模板方法(template),定义了算法的骨 架,具体子类需要去实现 其它的抽象方法operationr2,3,4
2) ConcreteClass 实现抽象方法operationr2,3,4, 以完成算法中特点子类的步

四、模板方法模式解决豆浆制作问题

豆浆类

//抽象类,表示豆浆
public abstract class SoyaMilk {//模板方法, make , 模板方法可以做成final , 不让子类去覆盖.final void make() {select(); addCondiments();soak();beat();}//选材料void select() {System.out.println("第一步:选择好的新鲜黄豆  ");}//添加不同的配料, 抽象方法, 子类具体实现abstract void addCondiments();//浸泡void soak() {System.out.println("第三步, 黄豆和配料开始浸泡, 需要3小时 ");}void beat() {System.out.println("第四步:黄豆和配料放到豆浆机去打碎  ");}
}

 两个子类

public class RedBeanSoyaMilk extends SoyaMilk {@Overridevoid addCondiments() {// TODO Auto-generated method stubSystem.out.println(" 加入上好的红豆 ");}}==================================================public class PeanutSoyaMilk extends SoyaMilk {@Overridevoid addCondiments() {// TODO Auto-generated method stubSystem.out.println(" 加入上好的花生 ");}}

测试

public class Client {public static void main(String[] args) {// TODO Auto-generated method stub//制作红豆豆浆System.out.println("----制作红豆豆浆----");SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk();redBeanSoyaMilk.make();System.out.println("----制作花生豆浆----");SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();peanutSoyaMilk.make();}}

能否让子类决定是否要添加材料呢?这就需要用到钩子方法

五、模板方法模式的钩子方法

1) 在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为“钩子”。
2) 还是用上面做豆浆的例子来讲解,比如,我们还希望制作纯豆浆,不添加任何的配料,请使用钩子方法对前面的模板方法进行改造
豆浆类——改进版
//抽象类,表示豆浆
public abstract class SoyaMilk {//模板方法, make , 模板方法可以做成final , 不让子类去覆盖.final void make() {select(); // 改进的地方if(customerWantCondiments()) {addCondiments();}soak();beat();}//选材料void select() {System.out.println("第一步:选择好的新鲜黄豆  ");}//添加不同的配料, 抽象方法, 子类具体实现abstract void addCondiments();//浸泡void soak() {System.out.println("第三步, 黄豆和配料开始浸泡, 需要3小时 ");}void beat() {System.out.println("第四步:黄豆和配料放到豆浆机去打碎  ");}// 改进的地方//钩子方法,决定是否需要添加配料boolean customerWantCondiments() {return true;}
}

子类

public class PureSoyaMilk extends SoyaMilk{@Overridevoid addCondiments() {// TODO Auto-generated method stub//空实现}@Overrideboolean customerWantCondiments() {// TODO Auto-generated method stub// 表示不需要添加材料return false;}}

测试

public class Client {public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println("----制作纯豆浆----");SoyaMilk pureSoyaMilk = new PureSoyaMilk();pureSoyaMilk.make();}}

六、模板方法模式在Spring框架应用的源码分析

在spring框架中有用到模板方法模式,ConfigurableApplicationContext中有方法refresh

 类图如下

 

七、注意事项和细节

1) 基本思想是: 算法只存在于一个地方,也就是在父类中,容易修改。 需要修改算法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改
2) 实现了最大化代码复用。 父类的模板方法和已实现的某些步骤会被子类继承而直接使用。
3) 既统一了算法,也提供了很大的灵活性。 父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步骤的实现。
4) 该模式的不足之处:每一个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大
5) 一般模板方法都加上 final 关键字, 防止子类重写模板方法 .
6) 模板方法模式使用场景: 当要完成在某个过程 该过程要执行一系列步骤 这一 系列的步骤基本相同 ,但其 个别步骤 在实现时 可能不同,通常考虑用模板方法模式来处理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/328066.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Docker基础三】Docker安装Redis

下载镜像 根据自己需要下载指定版本镜像,所有版本看这:Index of /releases/ (redis.io) 或 https://hub.docker.com/_/redis # 下载指定版本redis镜像 docker pull redis:7.2.0 # 查看镜像是否下载成功 docker images 创建挂载目录 # 宿主机上创建挂…

swing快速入门(四十)JList、JComboBox实现列表框

注释很详细,直接上代码 新增内容 🧧1.列表的属性设置与选项监听器 🧧2.下拉框的属性设置与选项监听器 🧧3.Box中组件填充情况不符合预期的处理方法 🧧4.LIst向Vector的转化方法 源码: package swing31_40;i…

ReentrantLock底层原理学习一

J.U.C 简介 Java.util.concurrent 是在并发编程中比较常用的工具类,里面包含很多用来在并发场景中使用的组件。比如线程池、阻塞队列、计时器、同步器、并发集合等等。并发包的作者是大名鼎鼎的 Doug Lea。我们在接下来的课程中,回去剖析一些经典的比较…

【数据结构】二叉树的创建和遍历:前序遍历,中序遍历,后序遍历,层次遍历

目录 一、二叉树的定义 1、二叉树的定义 2、二叉树的五种形态 二叉树的子树 : 3、满二叉树与完全二叉树 4、二叉树的性质 5、二叉树的存储结构 1、顺序存储 ​编辑 2、链式存储 二、二叉树的遍历 按照前序序列构建二叉树 1、前 (先) 序遍历(Preorder …

axure rp9添加当前日期、表单添加到中继器

1.[[Now.toLocaleDateString()]] [[Now.toLocaleTimeString()]]当前日期:2024/1/6 13:19:47 2. 输入内容添加到表单; 3.中继器的序号显示; 4. 中继器中添加按钮以及其他的;在中继器中添加动态面板,放入需要添加的按…

计数器的LED显示控制电路图

如图所示,图a中采用十进制七段存储-译码-驱动单元74143,此单元对所有段都有恒流输出。在电压为5V时每段电流约为15~22mA.七段译码器的BCD数据可以由脚17~20上取出。脚22用于进位,即当计数值到9后就为低电平,其余为高电平。利用这个信号可以控…

mysql视图和sql语句

mysql视图和sql语句 一.mysql视图1.数据的虚拟表示:2.简化复杂查询:3.安全性和权限控制:4.逻辑数据组织:5.更新限制:6.视图的创建: 二.mysq语句使用案列 MySQL的视图(View)是一个虚拟…

图神经网络|5.消息传递的计算方法 6.多层GNN的作用

5.消息传递的计算方法 边的存放方式 注意,在实际的边的实现方式中,并不是以邻接矩阵来进行实现的,这是因为在图的更新中,用邻接矩阵进行更新所占用的时间开销相对大,二是因为领接矩阵占用的空间大(N方&am…

每天刷两道题——第七天+第八天

力扣官网 1.1移动零 给定一个数组 n u m s nums nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序,在不复制数组的情况下原地对数组进行操作。 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 代码 def moveZeroea…

《3D数学基础-图形和游戏开发》阅读笔记 | 3D数学基础 (学习中 1.6更新)

文章目录 3D数学基础矢量/向量什么是向量点与矢量的关系 向量基础运算 向量加法向量基础运算 数乘 线性组合 - 坐标系的基如果选择不同的基向量会怎么样?- 张成(Span)的空间三维向量的张成空间线性相关与线性相关 矩阵与线性变换矩阵-几何意义线性变换矩阵乘法与线性…

Linux内核--网络协议栈(一)Socket通信原理和实例讲解

目录 一、引言 二、Socket ------>2.1、socket编程 ------>2.2、Socket的创建 三、收发数据 四、断开连接 五、删除套接字 六、网络 IO 一、引言 本章开始进入linux内核中网络部分的学习,先简单介绍一下socket套接字 二、Socket 一个数据包经由应用程序产生…

特斯拉难挽倒退?比亚迪为中国汽车市场改写历史

对于电动汽车这个新兴产业,特斯拉长期以来一直处于领头羊的位置,近年来也面临诸多测试。去年底欧洲报道特斯拉在瑞典遭遇罢工冲击,运营陷入诸多困扰,实在出人意料。更让人讶异的是,年终宣布新王者比亚迪在全球销量首次…