当前位置: 首页 > news >正文

【设计模式】模板方法模式 在java中的应用

设计模式

设计模式是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。这个术语是由Erich Gamma等人在1995年的书《设计模式:可复用面向对象软件的基础》中首次引入的。设计模式可以加快开发过程,提供一种通用的、重复使用的、优雅的解决方案,用于在特定的上下文中处理常见的设计问题。

设计模式可以分为三大类:创建型、结构型和行为型。创建型模式关注如何创建对象,结构型模式关注如何组合对象,而行为型模式则关注对象之间的通信。

模板方法模式

模板方法模式是一种行为设计模式,它在一个方法中定义了一个算法的骨架,并允许子类为一个或多个步骤提供实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。

在模板方法模式中,我们将不变的行为移至父类,将可变的行为留给子类实现。父类中的模板方法可以定义一系列的算法步骤,并且可以提供一个默认的实现。这样,子类在必要时可以覆盖这些方法,但是改变的是步骤的具体实现,而不是步骤的执行顺序。

模板方法模式是一种非常灵活的模式,它可以用来处理许多常见的编程问题,例如代码重用、代码组织和控制复杂性。

模板方法模式的定义

模板方法模式是一种行为设计模式,它在一个方法中定义了一个算法的骨架,并允许子类为一个或多个步骤提供实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。

模板方法模式的主要特点

  1. 代码复用和封装:模板方法模式通过将公共代码提取到父类中,实现了代码的复用。同时,它封装了具体步骤和数据,保护了算法的完整性和安全性。

  2. 提供统一的接口:父类提供了一个模板方法,定义了算法的骨架。这个模板方法对外提供了统一的接口,使得客户端不需要关心具体的实现细节。

  3. 支持变化:模板方法模式允许子类重写父类的某些步骤,这使得算法可以在不改变其结构的情况下,有选择地改变其行为。

  4. 控制子类的扩展:模板方法模式通过在模板方法中预定义钩子函数,可以控制子类的扩展。钩子是一种特殊的方法,它在父类中声明并给出默认实现,子类可以选择是否覆盖它。

  5. 延迟实现:模板方法模式中的具体步骤可以在子类中实现,这样可以延迟到子类中进行实现。这是所谓的“好莱坞原则”——别打电话给我们,我们会打电话给你。这种原则可以防止“依赖腐败”。

模板方法模式是一种非常灵活的模式,它可以用来处理许多常见的编程问题,例如代码重用、代码组织和控制复杂性。

模板方法模式的基本结构

模板方法模式主要包含以下几个部分:

  1. 抽象类(AbstractClass):这个类定义了一系列的方法,包括模板方法和一些基本方法。模板方法定义了算法的骨架,基本方法是算法中的一个步骤,可以是抽象的,也可以有默认的实现。

  2. 具体类(ConcreteClass):这个类继承抽象类,并实现抽象类中的抽象方法,这些方法是算法中的具体步骤。

UML图解释

-----------------
| AbstractClass |
-----------------
| +templateMethod() |
| #primitiveOperation1() |
| #primitiveOperation2() |
-----------------^|
-----------------
| ConcreteClass |
-----------------
| #primitiveOperation1() |
| #primitiveOperation2() |
-----------------

在这个UML图中:

  • AbstractClass 是一个抽象类,它定义了一个模板方法 templateMethod,以及两个基本方法 primitiveOperation1primitiveOperation2。模板方法 templateMethod 定义了算法的骨架,基本方法 primitiveOperation1primitiveOperation2 是算法中的一个步骤,可以是抽象的,也可以有默认的实现。

  • ConcreteClass 是一个具体类,它继承了 AbstractClass,并实现了 primitiveOperation1primitiveOperation2。这些方法是算法中的具体步骤。

实例背景介绍

假设我们正在开发一个工具库,其中有一个DataParser类,这个类的任务是读取数据,解析数据,然后处理数据。我们有两种类型的数据源:一种是从文件中读取的数据,另一种是从数据库中读取的数据。尽管读取数据的方式不同,但解析和处理数据的方式是相同的。

实例设计与实现

首先,我们定义一个抽象的DataParser类,这个类定义了解析数据的模板方法,模板方法中的一些步骤是抽象的,需要在子类中实现。

public abstract class DataParser {// Template methodpublic final void parseDataAndGenerateReport() {readData();processData();writeReport();}// Abstract methodsprotected abstract void readData();protected abstract void processData();// Common methodpublic void writeReport() {System.out.println("General Report Generation");}
}

然后,我们定义两个DataParser的子类:CSVDataParserDatabaseDataParser,它们分别实现了读取CSV文件和数据库的方法。

public class CSVDataParser extends DataParser {protected void readData() {System.out.println("Reading data from CSV file");}protected void processData() {System.out.println("Processing data from CSV file");}
}public class DatabaseDataParser extends DataParser {protected void readData() {System.out.println("Reading data from database");}protected void processData() {System.out.println("Processing data from database");}
}

代码解析

在上述代码中,DataParser类定义了一个模板方法parseDataAndGenerateReport(),这个方法包含了读取数据,处理数据和生成报告这三个步骤。其中,readData()processData()是抽象方法,需要在子类中实现,而writeReport()是一个具体方法,已经在DataParser类中实现。

CSVDataParserDatabaseDataParser类分别实现了readData()processData()方法,它们分别读取CSV文件和数据库中的数据,并处理这些数据。

这样,无论我们的数据来自于CSV文件还是数据库,我们都可以使用相同的方式来解析数据和生成报告,这就是模板方法模式的优点。

模板方法模式在Java API的应用

在Java API中,有许多地方使用了模板方法模式。例如,java.io.InputStreamjava.io.OutputStreamjava.io.Readerjava.io.Writer的所有非抽象方法,都依赖于这些类的抽象方法。例如,InputStream中的read()方法就是一个模板方法,它依赖于read(byte b[], int off, int len)这个抽象方法。

Java中模板方法模式的实际应用案例

一个常见的Java模板方法模式的应用是在Android的AsyncTask类中。AsyncTask是Android提供的一个轻量级的异步类,它可以直接继承使用。AsyncTask中定义了一些方法,如onPreExecute()doInBackground()onProgressUpdate()onPostExecute()。其中doInBackground()是抽象方法,必须在子类中实现,其他都是模板方法,有默认实现,可以根据需要在子类中重写。

以下是一个简单的示例:

public class DownloadTask extends AsyncTask<String, Integer, String> {protected void onPreExecute() {// 在主线程执行,用于进行一些界面上的初始化,比如显示一个进度条对话框等。}protected String doInBackground(String... params) {// 在子线程中执行,进行耗时操作,比如下载文件等。可以调用publishProgress方法来更新任务的进度。return "Downloaded file";}protected void onProgressUpdate(Integer... progress) {// 在主线程执行,用于更新进度信息。}protected void onPostExecute(String result) {// 在主线程执行,用于处理doInBackground方法的结果。}
}

在上述代码中,doInBackground()方法是抽象的,必须在子类中实现,其他的方法都有默认实现,可以在子类中重写。这就是典型的模板方法模式。

模板方法模式的优点

  1. 代码复用:模板方法模式通过在抽象类中定义算法的骨架,将具体步骤的实现延迟到子类,可以避免代码重复,提高代码复用性。

  2. 封装不变部分:模板方法模式封装了不变的算法步骤,保证了算法的稳定性和可靠性。

  3. 提供扩展点:模板方法模式提供了一个很好的扩展点,即在抽象类中定义的抽象方法,子类可以根据需要重写这些方法,以实现更多的功能。

模板方法模式的缺点

  1. 类数量增多:由于模板方法模式需要为每一个具体的算法步骤定义一个子类,因此可能会导致类的数量增多。

  2. 增加了系统的复杂性:模板方法模式虽然可以提高代码的复用性,但是由于需要定义多个子类,可能会增加系统的复杂性。

  3. 对子类的设计有限制:模板方法模式把基本方法的执行顺序写在模板方法里,这就限制了子类的行为。如果子类需要改变基本方法的执行顺序,那么就需要修改父类的模板方法,这违反了“开闭原则”。

模板方法模式是一种行为设计模式,它定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。

相关文章:

【设计模式】模板方法模式 在java中的应用

设计模式&#xff1a; 设计模式是对软件设计中普遍存在&#xff08;反复出现&#xff09;的各种问题&#xff0c;所提出的解决方案。这个术语是由Erich Gamma等人在1995年的书《设计模式&#xff1a;可复用面向对象软件的基础》中首次引入的。设计模式可以加快开发过程&#x…...

PVE纵览-安装系统卡“Loading Driver”的快速解决方案

PVE纵览-安装系统卡“Loading Driver”的快速解决方案 文章目录 PVE纵览-安装系统卡“Loading Driver”的快速解决方案摘要通过引导参数解决PVE安装卡在“Loading Driver”问题官方解决方法 关键字&#xff1a; PVE、 显卡、 Loading、 Driver、 nomodeset 摘要 在虚拟机…...

Lua资料

Lua脚本语言 cheet sheet Lua & c Lua与C API交互全面解析 Lua语言&#xff1a;和C语言的交互 Lua进阶用法之Lua和C的接口设计 Lua C API 简介 C和Lua之间的相互调用 深入Lua&#xff1a;用户数据userdata 基本数据类型 之 UserData calling-lua-from-c/ Embedding Lua i…...

【C语言】值传递和地址传递

值传递 引用传递&#xff08;传地址&#xff0c;传引用&#xff09;的区别 传值&#xff0c;是把实参的值赋值给行参 &#xff0c;那么对行参的修改&#xff0c;不会影响实参的值。 传地址&#xff0c;是传值的一种特殊方式&#xff0c;只是他传递的是地址&#xff0c;不是普通…...

PyTorch 中使用自动求导计算梯度

使用 PyTorch 进行自动求导和梯度计算 在 PyTorch 中&#xff0c;张量的 requires_grad 属性决定了是否需要计算该张量的梯度。设置为 True 的张量会在计算过程中记录操作&#xff0c;以便在调用 .backward() 方法时自动计算梯度。通过构建计算图&#xff0c;PyTorch 能够有效…...

Oracle Instant Client 23.5安装配置完整教程

Oracle Instant Client 23.5安装配置完整教程 简介环境要求安装步骤1. 准备工作目录2. 下载Oracle Instant Client3. 解压Instant Client4. 安装依赖包5. 配置系统环境5.1 配置库文件路径5.2 配置环境变量 6. 配置Oracle钱包&#xff08;可选&#xff09; 验证安装常见问题解决…...

【jvm】方法区的理解

目录 1. 说明2. 方法区的演进3. 内部结构4. 作用5.内存管理 1. 说明 1.方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码缓存等数据。它是各个线程共享的内存区域。2.尽管《Java虚拟机规范》中把方法区描述为堆的一个逻辑部分&#xff0c;但它却…...

ES-针对某个字段去重后-获取某个字段值的所有值

针对上面表的数据&#xff0c;现在想根据age分组&#xff0c;并获取每个分组后的name有哪些(去重后)。 select age, GROUP_CONCAT(DISTINCT(name)) from testtable group by age ; 结果&#xff1a; 如果想要增加排序&#xff1a; SELECT age, GROUP_CONCAT(DISTINCT name)…...

百度 2025届秋招提前批 文心一言大模型算法工程师

文章目录 个人情况一面/技术面 1h二面/技术面 1h三面/技术面 40min 个人情况 先说一下个人情况&#xff1a; 学校情况&#xff1a;211本中9硕&#xff0c;本硕学校都一般&#xff0c;本硕都是计算机科班&#xff0c;但研究方向并不是NLP&#xff0c;而是图表示学习论文情况&a…...

sglang 部署Qwen2VL7B,大模型部署,速度测试,深度学习

sglang 项目github仓库&#xff1a; https://github.com/sgl-project/sglang 项目说明书&#xff1a; https://sgl-project.github.io/start/install.html 资讯&#xff1a; https://github.com/sgl-project/sgl-learning-materials?tabreadme-ov-file#the-first-sglang…...

fastadmin操作数据库字段为json、查询遍历each、多级下拉、union、php密码设置、common常用函数的使用小技巧

数据库中遇到的操作 查询字段是json的某个值 //获取数据库中某个字段是json中得某个值&#xff0c;进行查询&#xff0c;goods是表中字段&#xff0c;brand_id是json中要查詢的字段。//数据类型一定要对应要不然查询不出来。$map[json_extract(goods, "$.brand_id")]…...

UniApp在Vue3的setup语法糖下自定义组件插槽详解

UniApp在 Vue3的 setup 语法糖下自定义组件插槽详解 UniApp 是一个基于 Vue.js 的跨平台开发框架&#xff0c;可以用来开发微信小程序、H5、App 等多种平台的应用。Vue 3 引入了 <script setup> 语法糖&#xff0c;使得组件的编写更加简洁和直观。本文将详细介绍如何在 …...

springboot上传下载文件

RequestMapping(“bigJson”) RestController Slf4j public class TestBigJsonController { Resource private BigjsonService bigjsonService;PostMapping("uploadJsonFile") public ResponseResult<Long> uploadJsonFile(RequestParam("file")Mul…...

Python学习从0到1 day29 Python 高阶技巧 ⑦ 正则表达式

目录 一、正则表达式 二、正则表达式的三个基础方法 1.match 从头匹配 2.search&#xff08;匹配规则&#xff0c;被匹配字符串&#xff09; 3.findall&#xff08;匹配规则&#xff0c;被匹配字符串&#xff09; 三、元字符匹配 单字符匹配&#xff1a; 注&#xff1a; 示例&a…...

机器学习-web scraping

Web Scraping&#xff0c;通常称为网络抓取或数据抓取&#xff0c;是一种通过自动化程序从网页中提取数据的技术。以下是对Web Scraping的详细解释&#xff1a; 一、定义与原理 Web Scraping是指采用技术手段从大量网页中提取结构化和非结构化信息&#xff0c;并按照一定的规…...

移远通信5G RedCap模组RG255C-CN通过中国电信5G Inside终端生态认证

近日&#xff0c;移远通信5G RedCap模组RG255C-CN荣获中国电信颁发的5G Inside终端生态认证证书。这表明&#xff0c;该产品在5G基本性能、网络兼容性、安全特性等方面已经过严格评测且表现优异&#xff0c;将进一步加速推动5G行业终端规模化应用。 中国电信5G Inside终端生态认…...

Javaweb梳理17——HTMLCSS简介

Javaweb梳理17——HTML&CSS简介 17 HTML&CSS简介17.1 HTML介绍17.2 快速入门17.3 基础标签17.3 .1 标题标签17.3.2 hr标签17.3.3 字体标签17.3.4 换行17.3.8 案例17.3.9 图片、音频、视频标签17.3.10 超链接标签17.3.11 列表标签17.3.12 表格标签17.3.11 布局标签17.3.…...

【Android、IOS、Flutter、鸿蒙、ReactNative 】自定义View

Android Java 自定义View 步骤 创建一个新的Java类&#xff0c;继承自View、ViewGroup或其他任何一个视图类。 如果需要&#xff0c;重写构造函数以支持不同的初始化方式。 重写onMeasure方法以提供正确的测量逻辑。 重写onDraw方法以实现绘制逻辑。 根据需要重写其他方法&…...

win11跳过联网激活步骤

win11跳过联网激活步骤 win11跳过联网激活步骤方法一&#xff1a;使用Shift F10快捷键&#xff08;推荐&#xff09;1. 启动Windows 112. 选择键盘布局或输入法3. 是否想要添加第二种键盘布局4. 让我们为你连接到网络5. 调出管理员模式CMD6. 耐心等待自动重启7. 启动Windows 1…...

利用c语言详细介绍下冒泡排序

软件开发过程中&#xff0c;排序算法是常规且使用众多的方法之一&#xff0c;而冒泡算法又是排序算法中最常规且基本的算法。今天我们利用c语言&#xff0c;图文详细介绍下冒泡算法。 一、图文介绍 我们输入一个数组&#xff0c;数组为【10&#xff0c;5&#xff0c;3&#xf…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

Ubuntu系统多网卡多相机IP设置方法

目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机&#xff0c;交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息&#xff0c;系统版本&#xff1a;Ubuntu22.04.5 LTS&#xff1b;内核版本…...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码&#xff1a;冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...