设计模式——模板设计模式(Template Method)

模板设计-base

什么是模板?

举个简单的例子,以AABB的格式,写出一个词语,你可能会想到,明明白白,干干净净等,
这个AABB就是一个模板,对模板心中有了一个清晰的概念之后,我们再来看今天我们的内容,模板设计。

实现思路

我们在父类中,定义处理流程的框架,子类中实现具体处理

要如何实现这样的思路呢?

在父类中定义多个抽象方法,然后由一个模板方法来进行调用,决定如何使用这些模板方法,就形成了处理流程的框架。

子类继承父类,只需要实现抽象方法。这样一来模板方法就留在了父类中,各个子类都可以有自己的实现方式。

代码实现

在这里插入图片描述

在这里插入图片描述

我们定义AbstractDisplay作为父类里面有open、print、close 3个抽象方法,一个display模板方法

charDisplay和StringDisplay作为AbstractDisplay的子类,去实现各自的open、print、close方法。
最终我们用子类统一去调用父类已经实现的display模板方法,查看效果。

public abstract class AbstractDisplay {/*** 交给字类实现的抽象方法(1) open*/public abstract void open();/*** 交给字类实现的抽象方法(2)print*/public abstract void print();/*** 交给字类实现的抽象方法(3)close*/public abstract void close();/*** 模板方法,先调用open在调用5次print方法,最后调用close。* 可以看出,父类中只调用抽象方法,但不实现抽象方法,具体实现交给子类。*/public final void display(){open();for (int i = 0; i < 5; i++) {print();}close();}
}

接下来让我们看看CharDisplayStringDisplay是如何实现的。

public class CharDisplay extends AbstractDisplay{private char character;public CharDisplay(char c){this.character = c;}@Overridepublic void open() {System.out.print("<<");}@Overridepublic void print() {System.out.print(character);}@Overridepublic void close() {System.out.println(">>");}
}
public class StringDisplay extends AbstractDisplay{private String string;private Integer times;public StringDisplay(String string) {this.string = string;times = string.toCharArray().length;}@Overridepublic void open() {System.out.print("+");for (int i = 0; i < times; i++) {System.out.print("-");}System.out.println("+");}@Overridepublic void print() {System.out.println("|"+string+"|");}@Overridepublic void close() {System.out.print("+");for (int i = 0; i < times; i++) {System.out.print("-");}System.out.println("+");}
}

让我们在Main类中调用试试看吧

public class Main3 {public static void main(String[] args) {//生成一个持有'H'的CharDisplay实例AbstractDisplay d1 = new CharDisplay('H');//生成一个持有'Hello,world.'的StringDisplay类的实例AbstractDisplay d2 = new StringDisplay("Hello,world.");//由于d1、d2都是AbstractDisplay的实例,可以调用继承的display方法,实际的程序行为取决于CharDisplay类和StringDisplay类的具体实现d1.display();d2.display();}
}

输出结果
在这里插入图片描述
我们创建了一个AbstractDisplay的模板,最终却生成了两种不同的结果!就像AABB的模板最终可以生成明明白白和干干净净一样!

恭喜你!!掌握了模板设计模式的基本使用!接下来让我们拓展一下思路。

思路拓展

可以使逻辑处理通用化

使用 Template Method模式究竟能带来什么好处呢?

让我们先看看Template Method模式的类图是什么样的
在这里插入图片描述

使用 Template Method模式究竟能带来什么好处呢?

这里,它的优点是由于在父类的模板方法中编写了算法,因此无需在每个子类中再重复编写算法。

例如,我们没使用 Template Method模式,而是使用文本编辑器的复制和粘贴功能编写了多个ConcreteClass角色。此时,会出现ConcreteClass1、ConcreteClass2、Concreteclass3 等很多相似的类。编写完成后立即发现了Bug还好,但如果是过一段时间才发现在Concreteclass1中有 Bug,该怎么办呢?这时,我们就必须将这个 Bug的修改反映到所有的 ConcreteClass 角色中才行。

关于这一点,如果是使用 Template Method模式进行编程,当我们在模板方法中发现Bug时只需要修改模板方法即可解决问题

父类与子类之间的协助

在 Template Method模式中,父类和子类是紧密联系、共同工作的。因此,在子类中实现父类中声明的抽象方法时,必须要理解这些抽象方法被调用的时机。在看不到父类的源代码的情况下想要编写出子类是非常困难的。

模板设计-plus

练习题一

java.io.Inputstream类使用了Template Method模式。请阅读官方文档(JDK的API参考资料 ),从中找出需要用java.io.Inputstream 的子类去实现的方法。

练习题二

上面给出的AbstractDisplay类的display方法如下

public final void display(){....
}
这里使用了final修饰符,请问这是想表达什么意思呢?

练习题三

如果想要让示例程序中的open、print、close方法可以被具有继承关系的类和同一程序包中的类调用,但是不能被无关的其他类调用,应当怎么做呢?

练习题四

Java中的接口与抽象类很相似。接口同样也是抽象方法的集合,但是在TemplateMethod 模式中,我们却无法使用接口来扮演AbstractClass角色,请问这是为什么呢?

答案

练习题一

查阅文档后,你就会知道,InputStream是一个抽象类,其中需要子类实现的抽象方法只有一个就是read方法啦!
在这里插入图片描述

在这里插入图片描述

练习题二

final关键字修饰方法的时候,表示定义在父类中的模板方法display无法在子类中进行重写,这正和我们期望的一致,我们希望模板方法由父类直接实现,即父类直接定义抽象方法的使用框架,不希望子类再去进行重写,使用模板设计模式时,子类也不应该重写模板方法。

练习题三

可以将AbstractDisplay类中的open,print,close方法的可见性声明为protected。这样就可以让继承该类的子类调用这些方法,而其他包中的类无法调用这些方法(不过同一个包中的类依然可以调用这些方法)。

练习题四

这是因为 TemplateMethod模式中的AbstractClass角色必须实现处理的流程。在抽象类中可以实现一部分方法(例如 AbstractDisplay类中的display方法),但是在接口中是无法实现方法的。因此,在TemplateMethod 模式中,无法用接口替代抽象类。

在Java8之前以上结论成立,在Java8之后,引入了defualt关键字,增强了接口的功能,使得接口也可以实现方法。

知识关联性

Factory Method 模式(工厂模式)

是将 Template Method 模式用于生成实例的一个典型例子。

Strategy模式(策略模式)

在 Template Method 模式中,可以使用继承改变程序的行为。这是因为 Template Method 模式在父类中定义程序行为的框架,在子类中决定具体的处理。
与此相对的是 Strategy模式,它可以使用委托改变程序的行为。与Template Method 模式中改变部分程序行为不同的是,Strategy模式用于替换整个算法。

模板设计模式(Template Method)的讲解到此就结束啦,感谢阅读。💕

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

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

相关文章

docker————docker的安装

目录 docker的安装 1、安装yum-utils工具 2、安装yum仓库 3、安装docker引擎 4、设置开机启动&#xff0c;并立即启动 5、测试 docker的安装 docker的官网Docker Docs 我才用的linux版本是rocky&#xff0c;使用的是最小安装 1、安装yum-utils工具 [rootbogon yum.rep…

环境变量(全)

概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数 如&#xff1a;我们在编写C/C代码的时候&#xff0c;在链接的时候&#xff0c;从来不知道我们的所链接的动态静态库在哪里&#xff0c;但是照样可以链接成功&#xff0c;生成可执…

今日arXiv最热NLP大模型论文:揭露大语言模型短板,北京大学提出事件推理测试基准

人工智能领域又一里程碑时刻&#xff01;北京大学、北京智源人工智能研究院等机构联合推出大型事件推理评测基准 。这是首个同时在知识和推理层面全面评估大模型事件推理能力的数据集。 总所周知&#xff0c;事件推理需要丰富的事件知识和强大的推理能力&#xff0c;涉及多种推…

consul启动Error_server_rejoin_age_max (168h0m0s) - consider wiping your data dir

consul 启动报错&#xff1a; consul[11880]: 2024-05-12T08:37:51.095-0400 [ERROR] agent: startup error: error"refusing to rejoin cluster because server has been offline for more than the configured server_rejoin_age_max (168h0m0s) - consider wiping you…

【GD32】02-ADC模拟数字转换器

ADC 在电子和通信技术中&#xff0c;ADC&#xff08;模拟数字转换器&#xff09;是一种将模拟信号转换为数字信号的电子设备。这种转换是电子系统中非常关键的一个环节&#xff0c;因为数字信号更易于处理、存储和传输。ADC的工作原理通常包括采样、保持、量化和编码等步骤。采…

http协议 tomcat如何访问资源 servlet理论介绍

tomcat介绍 bin是启动命令&#xff1b; conf是配置&#xff0c;可以修改端口号&#xff1b; lib是依赖的jar包&#xff1b; logs是日志 webapps是重点&#xff0c;在这里新建我们自己的javaWeb项目 tomcat如何访问资源 tomcat通过统一资源定位符&#xff08;URL&#xff09;来…

乡村振兴与农村基础设施建设:加大农村基础设施建设投入,提升农村公共服务水平,改善农民生产生活条件,构建宜居宜业的美丽乡村

一、引言 乡村振兴是我国现代化进程中的重要战略&#xff0c;而农村基础设施建设则是乡村振兴的基石。随着城市化进程的加快&#xff0c;农村基础设施建设滞后的问题日益凸显&#xff0c;成为制约乡村发展的瓶颈。因此&#xff0c;加大农村基础设施建设投入&#xff0c;提升农…

打造一套在线教育系统,如何在教育这个慢行业打造品牌?

品牌对于教育行业非常重要&#xff0c;很多从事教育行业的朋友一直想塑造属于自己的品牌形象&#xff0c;但做起来却没那么容易。因为教育行业相对来说是一个慢行业&#xff0c;用户必须看到效果才会认可&#xff0c;而教育的效果往往需要经过长期的学习才能看到。 我觉得&…

AI大模型探索之路-训练篇21:Llama2微调实战-LoRA技术微调步骤详解

系列篇章&#x1f4a5; AI大模型探索之路-训练篇1&#xff1a;大语言模型微调基础认知 AI大模型探索之路-训练篇2&#xff1a;大语言模型预训练基础认知 AI大模型探索之路-训练篇3&#xff1a;大语言模型全景解读 AI大模型探索之路-训练篇4&#xff1a;大语言模型训练数据集概…

华为OD机试 - 执行任务赚积分 - 动态规划(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷+C卷)》。 刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。 一、题目描述 现有 N 个任…

Gradle基础学习(六) 认识任务Task

理解Gradle中的任务 Gradle的构建过程基于任务&#xff08;Task&#xff09;的概念&#xff0c;而每个任务都可以包含一个或多个动作&#xff08;Action&#xff09;。 任务是构建中执行的一些独立的工作单元&#xff0c;例如编译类、创建JAR、生成Javadoc或将存档发布到仓库…

4.5网安学习第四阶段第五周回顾(个人学习记录使用)

本周重点 ①部署域环境&#xff08;Win2008&#xff09; ②域组策略 ③域内信息收集 ④(重点)哈希传递攻击PTH ⑤MS14-068 提权漏洞 ⑥黄金票据伪造 ⑦白银票据伪造 ⑧ZeroLogon (CVE-2020-1472) 漏洞复现 本周主要内容 ①部署域环境&#xff08;Win2008&#xff09;…

【算法】滑动窗口——串联所有单词的子串

今天来以“滑动窗口”的思想来详解一道比较困难的题目——串联所有单词的子串&#xff0c;有需要借鉴即可。 目录 1.题目2.下面是示例代码3.总结 1.题目 题目链接&#xff1a;LINK 这道题如果把每个字符串看成一个字母&#xff0c;就是另外一道中等难度的题目&#xff0c;即&…

对象,字符串的解构赋值

大家想了解更多&#xff0c;可以去看阮一峰的ECMAScript6(ES6)标准入门课程 对象 简介 解构不仅可以用于数组&#xff0c;还可以用于对象。 let { foo, bar } { foo: aaa, bar: bbb }; foo // "aaa" bar // "bbb" 对象的解构与数组有一个重要的不同。…

[CAM_REQ_MGR_EVENT_MAX]高通6225平台相机老化异常重启

报错log 相机老化出现20/7万比例的老化异常重启&#xff0c;具体报错log入下 <4>[ 167.506585] [1970:01:02 18:52:26](0) [0:swapper/0]cam_v4l2_event_queue_notify_error: 251 callbacks suppressed 7 3339<6>[ 167.506602] [1970:01:02 18:52:26](0) [0:swap…

面试试题一

封装&#xff08;Encapsulation&#xff09; 面试问题&#xff1a; 封装在面向对象编程中扮演什么角色&#xff1f;如何在Java中实现封装&#xff1f;有哪些最佳实践可以帮助提高类的封装性&#xff1f; 详细答案&#xff1a; 封装的角色&#xff1a; 封装是面向对象编程的核…

CMake 的继承关系

1. CMake如何确定继承关系 在 CMake 中&#xff0c;父子关系是通过文件系统中的目录结构来定义的。当你在一个目录中创建一个 CMakeLists.txt 文件时&#xff0c;该目录就被视为一个 CMake 项目的目录&#xff0c;而该文件中的内容将被用于配置和构建该目录中的项目。 当你在父…

不同路径| 和 不同路径||

不同路径| 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&#xf…

Tomcat启动闪退问题解决办法

本文将通过一系列诊断步骤帮助您找出原因&#xff0c;并提供相应的解决办法。 诊断步骤 查看日志文件 Tomcat的日志文件是解决启动问题的第一线工具。查看logs目录下的catalina.out和其他日志文件&#xff0c;这些文件经常记录了错误信息和系统崩溃的线索。 cat /path/to/to…

C++编程与朱元墇的关系

学编程和英语没关系&#xff0c;我说这句话&#xff0c;没人会相信&#xff0c;也不会有人说我什么哗众取宠。 我说学编程和朱元墇有关系&#xff0c;一定有人说我放P&#xff0c;其实这个P也和朱元墇有关系&#xff0c; 和朱元墇有什么P关系啊。 真有这P事啊&#xff0c; 朱元…