模板方法模式——定义算法的框架

1、简介

1.1、概述

模板方法模式是结构最简单的行为型设计模式,在其结构中只存在父类与子类之间的继承关系。通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中。在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。模板方法模式提供了一个模板方法来定义算法框架,而某些具体步骤的实现可以在其子类中完成。

模板方法模式是一种基于继承的代码复用基本技术。

1.2、定义

模板方法模式(Template Method Pattern):定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。模板方法模式是一种类行为型模式。

2、解析

2.1、UML类图

模板方法模式结构比较简单,其核心是抽象类和其中的模板方法的设计,其结构如下图所示:
在这里插入图片描述

  1. AbstractClass(抽象类):在抽象类中定义了一系列基本操作(Primitive Operations),这些基本操作可以是具体的,也可以是抽象的。每个基本操作对应算法的一个步骤,在其子类中可以重定义或实现这些步骤。同时,在抽象类中实现了一个模板方法(Template Method),用于定义一个算法的框架。模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽象类的子类中实现的基本方法,还可以调用其他对象中的方法。
  2. ConcreteClass(具体子类):它是抽象类的子类,用于实现在父类中声明的抽象基本操作以完成子类特定算法的步骤,也可以覆盖在父类中已经实现的具体基本操作。

2.2、模板方法和基本方法

在使用模板方法模式时,开发抽象类的软件设计师和开发具体子类的软件设计师之间可以进行协作。一个设计师负责给出一个算法的轮廓和框架,另一些设计师则负责给出这个算法的各个逻辑步骤。实现这些具体逻辑步骤的方法即为基本方法,而将这些基本方法汇总起来的方法即为模板方法,模板方法模式的名字也因此而来。

  1. 模板方法:一个模板方法是定义在抽象类中的、把基本操作方法组合在一起形成一个总算法或一个总行为的方法。这个模板方法定义在抽象类中,并由子类不加以修改地完全继承下来(在Java语言中,可以将模板方法定义为final方法)。模板方法是一个具体方法,它给出了一个顶层逻辑框架,而逻辑的组成步骤在抽象类中可以是具体方法,也可以是抽象方法。由于模板方法是具体方法,因此模板方法模式中的抽象层只能是抽象类,而不是接口。
  2. 基本方法:基本方法是实现算法各个步骤的方法,是模板方法的组成部分。基本方法又可以分为3种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(Hook Method)。

(1)抽象方法:一个抽象方法由抽象类声明,由其具体子类实现。在Java语言里一个抽象方法以abstract关键字标识。
(2)具体方法:一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。
(3)钩子方法:一个钩子方法由一个抽象类或具体类声明并实现,而其子类可能会加以扩展。通常在父类中给出的实现是一个空实现,并以该空实现作为方法的默认实现,当然钩子方法也可以提供一个非空的默认实现。

在模板方法模式中,钩子方法有两类。第一类钩子方法可以与一些具体步骤“挂钩”,以实现在不同条件下执行模板方法中的不同步骤。这类钩子方法的返回类型通常是boolean类型,方法名一般为is×××(),用于对某个条件进行判断。如果条件满足则执行某一步骤,否则将不执行。代码片段如下:

// 模板方法
public void template(){open();display();if(isPrint()){print();}// 构子方法public boolean isPrint(){return true;}
}

在以上代码中,isPrint()方法即是钩子方法,它可以决定print()方法是否执行。一般情况下,钩子方法的返回值为true。如果不希望某方法执行,可以在其子类中覆盖钩子方法,将其返回值改为false即可。这种类型的钩子方法可以控制方法的执行,对一个算法进行约束。

还有一类钩子方法就是方法体为空的具体方法,子类可以根据需要覆盖或者继承这些钩子方法。与抽象方法相比,这类钩子方法的好处在于子类如果没有覆盖父类中定义的钩子方法,编译也可以正常通过,但是如果没有覆盖父类中声明的抽象方法,编译将报错。

模板方法模式中,抽象类的典型代码如下:

abstract class AbstractClass{// 模板方法// 基本方法——具体方法public void primitiveOperation1(){// 实现代码}// 基本方法——抽象方法public abstract void primitiveOperation2();// 基本方法——构子方法public abstract void primitiveOperation3(){}
}

在抽象类中,模板方法templateMethod()定义了算法的框架,在模板方法中调用基本方法以实现完整的算法。每一个基本方法如primitiveOperation1()、primitiveOperation2()等均实现了算法的一部分,对于所有子类都相同的基本方法可由父类提供具体实现,例如primitiveOperation1()。否则在父类中声明为抽象方法或钩子方法,由不同的子类提供不同的实现,例如primitiveOperation2()和primitiveOperation3()。

可在抽象类的子类中提供抽象步骤的实现,也可覆盖父类中已经实现的具体方法。具体子类的典型代码如下:

public ConcreteClass extends AbstractClass{public void primitiveOperation2(){// 实现代码}public void primitiveOperation3(){// 实现代码}
}

在模板方法模式中,由于面向对象的多态性,子类对象在运行时将覆盖父类对象,子类中定义的方法也将覆盖父类中定义的方法。因此程序在运行时,具体子类的基本方法将覆盖父类中定义的基本方法,子类的钩子方法也将覆盖父类的钩子方法,从而可以通过在子类中实现的钩子方法对父类方法的执行进行约束,实现子类对父类行为的反向控制。

3、模板方法模式总结

模板方法模式是一种基于继承的代码复用技术,它体现了面向对象的诸多重要思想,是一种使用频率较高的模式。模板方法模式广泛应用于框架设计(例如Spring、JUnit等)中,以确保通过父类来控制处理流程的逻辑顺序(例如框架的初始化、测试流程的设置等)。

3.1、主要优点

  1. 模板方法模式在父类中形式化地定义一个算法,而由它的子类来实现细节的处理。在子类实现详细的处理算法时并不会改变算法中步骤的执行次序。
  2. 模板方法模式是一种代码复用技术,它在类库设计中尤为重要。它提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为。它鼓励恰当使用继承来实现代码复用。
  3. 模板方法模式可实现一种反向控制结构。通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执行。
  4. 在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则。

3.2、主要缺点

模板方法模式的主要缺点是:需要为每一个基本方法的不同实现提供一个子类。如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象。此时,可结合桥接模式来进行设计。

3.3、适用场景

  1. 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类来实现。即一次性地实现一个算法的不变部分,并将可变的行为留给子类来实现。
  2. 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
  3. 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。

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

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

相关文章

vscode插件不能搜索安装

1 现象 vscode搜索自己的插件,报错: Error while fetching extensions. HXR failed2 原因 之前用vscode开发golang语言,设置了proxy代理,所以导致错误,删除即可 重启vscode 3 结果

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--功能实现【四】

文章目录 SSM--功能实现实现功能06-修改家居信息需求分析/图解思路分析代码实现注意事项和细节 实现功能07-删除家居信息需求分析/图解思路分析代码实现 实现功能08-分页显示列表需求分析/图解思路分析代码实现完成测试分页显示效果 SSM–功能实现 实现功能06-修改家居信息 需…

git之reflog分析

写在前面 本文一起看下reflog命令。 1:场景描述 在开发的过程中,因为修改错误,想要通过git reset命令恢复到之前的某个版本,但是选择提交ID错误,导致多恢复了一个版本,假定,该版本对应的内容…

macOS 环境变量加载探究

使用 macOS 安装环境,见到过很数种环境变量配置方法,每次也都是按照别人的代码,人家配置在哪 我就配置在哪,其实不太清楚有什么区别,决定记录下。 本机 macOS 13.3,从 macOS Catalina(10.15) 开始&#xf…

用html+javascript打造公文一键排版系统15:一键删除所有空格

现在我们来实现一键删除所有空格的功能。 一、使用原有的代码来实现,测试效果并不理想 在这之前我们已经为String对象编写了一个使用正则表达式来删除所有空格的方法: //功能:删除字符串中的所有空格 //记录:20230726创建 Stri…

腾讯云-宝塔添加MySQL数据库

1. 数据库菜单 2. 添加数据库 3. 数据库添加成功 4. 上传数据库文件 5. 导入数据库文件 6. 开启数据库权限 7. 添加安全组 (宝塔/腾讯云) 8. Navicat 连接成功

python 封装sql 增删改查连接MySQL

select * from Teacher limit 10 连接字符串配置MysqlConfig.py class MysqlConfig:HOST 192.168.56.210PORT 3306USER rootPASSWORD 1qaz0987654321DBStudentDBCHARSET utf8封装增删改查MysqlConnection.py Author: tkhywang 2810248865qq.com Date: 2023-06-19 15:44:48 Las…

rest api client code generator

一、搜索:REST API Client Code Generator 二、 安装成功后 配置java环境和node环境

线性代数 | 机器学习数学基础

前言 线性代数(linear algebra)是关于向量空间和线性映射的一个数学分支。它包括对线、面和子空间的研究,同时也涉及到所有的向量空间的一般性质。 本文主要介绍机器学习中所用到的线性代数核心基础概念,供读者学习阶段查漏补缺…

743. 网络延迟时间

有 n 个网络节点,标记为 1 到 n。 给你一个列表 times,表示信号经过 有向 边的传递时间。 times[i] (ui, vi, wi),其中 ui 是源节点,vi 是目标节点, wi 是一个信号从源节点传递到目标节点的时间。 现在,…

JNI之Java实现蓝牙交互

蓝牙概述 蓝牙,是一种支持设备短距离通信(一般10m内)的无线电技术,能在包括移动电话、PDA、无线耳机、笔记本电脑、相关外设等众多设备之间,通过蓝牙设备之间的无线通信实现数据传输,实现数据传输&#xf…

【计算机视觉|语音分离】期望在嘈杂环境中聆听:一个用于语音分离的不依赖于讲话者的“音频-视觉模型”

本系列博文为深度学习/计算机视觉论文笔记,转载请注明出处 标题:Looking to Listen at the Cocktail Party: A Speaker-Independent Audio-Visual Model for Speech Separation 链接:Looking to listen at the cocktail party: a speaker-in…

【网络工程】网络流量分析工具 Wireshark

文章目录 第一章:WireShark介绍第二章:WireShark应用第三章:Wireshark 实战 第一章:WireShark介绍 Wireshark (前身 Ethereal):它是一个强大的网络包分析工具 ! 此工具主要是用来捕获网络数据包的,并且自动…

zookeeper --- 基础篇

一、zookeeper简介 1.1、什么是zookeeper zookeeper官网:https://zookeeper.apache.org/ 大数据生态系统里的很多组件的命名都是某种动物或者昆虫,他是用来管 Hadoop(大象)、Hive(蜜蜂)、Pig(小 猪)的管理员。顾名思义就是管理…

zabbix触发器标签提取监控项子字符串实现对应告警恢复

0 实验环境 zabbix 6.0 1 监控项 1.1 监控项设置 通过zabbix agent自定义监控项,读取某文件内容模拟日志/trap告警,测试获取触发器标签中提取子字符串功能,以及相同标签的触发器自动恢复功能。 1.2 手工运行 手动触发之后,模…

在centos7上使用非编译方式安装ffmpeg

很多在centos7上安装ffmpeg的教程都需要使用编译方式的安装;编译时间较长而且需要配置; 后来搜索到可以通过加载rpm 源的方式实现快速便捷操作 第一种方式: 首先需要安装yum源: yum install epel-release yum install -y https://mirrors.…

echarts 图例组件legend配置

legend 图例组件展示不同系列的图表类型标记、颜色、和名称。可以通过点击来控制哪个系列不展示。对于饼图来说,控制哪个数据不展示。 $> echarts5.4.0简单画一个饼图作为示例,设置legend:{show:true}展示图例。 const options {legend: {show: true,},series…

Java List(列表)

List 是一个有序、可重复的集合,集合中每个元素都有其对应的顺序索引。List 集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。List 集合默认按元素的添加顺序设置元素的索引,第一个添加到 List 集合中的元素的索引为 0&#xff…

ELK 企业级日志分析系统(ElasticSearch、Logstash 和 Kiabana 详解)

目录 一.ELK简介 1.1ELK的概述 1.2ELK的组成 1.2.1 ElasticSearch 1.2.2 Logstash 1.2.3 Kibana 1.2.4 小总结 1.3可以添加其他组件 1.4filebeat 结合 logstash 带来好处 1.5日志处理的步骤 二.Elasticsearch 2.1Elasticsearch概述 2.2Elasticsearch核心概念 2.2.1接近…

使用可视化docker浏览器,轻松实现分布式web自动化

01、前言 顺着docker的发展,很多测试的同学也已经在测试工作上使用docker作为环境基础去进行一些自动化测试,这篇文章主要讲述我们在docker中使用浏览器进行自动化测试如果可以实现可视化,同时可以对浏览器进行相关的操作。 02、开篇 首先…