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

0128_模板方法(Template Method)

模板方法(Template Method)

意图

定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变算法结构的情况下,重新定义算法中的某些特定步骤。

UML 图

TemplateMethod

优点

  1. 代码复用:将公共行为移到父类中,避免代码重复
  2. 封装不变部分:固定算法结构,保护核心算法不被修改
  3. 扩展性好:通过子类扩展具体实现,符合开闭原则
  4. 便于维护:算法修改只需在父类中进行,子类不受影响
  5. 提高灵活性:子类可以灵活实现特定步骤,而不影响整体结构

缺点

  1. 限制扩展性:算法框架固定,可能限制子类的灵活性
  2. 增加系统复杂度:每个不同实现都需要一个子类,可能导致类数量增加
  3. 违反里氏替换原则:如果子类对模板方法进行重写,可能破坏父类定义的行为
  4. 调试困难:模板方法中的步骤调用可能在多个子类中实现,调试较复杂
  5. 可能产生过多抽象:如果步骤划分过细,可能导致系统过于抽象

代码示例

以人类和机器人执行任务的不同方式为例:

1. 抽象模板类 (Abstract Template Class)

// 抽象任务模板
public abstract class TaskTemplate {private String taskName;public TaskTemplate(String taskName) {this.taskName = taskName;}// 模板方法 - 定义算法骨架 (final防止子类重写)public final void executeTask() {System.out.println("🚀 开始执行任务: " + taskName);prepareEnvironment();performCoreTask();cleanup();generateReport();System.out.println("✅ 任务完成: " + taskName + "\n");}// 具体方法 - 通用实现private void prepareEnvironment() {System.out.println("🔧 准备执行环境...");}// 抽象方法 - 由子类实现protected abstract void performCoreTask();// 钩子方法 - 默认实现,子类可选择重写protected void cleanup() {System.out.println("🧹 执行默认清理操作...");}// 具体方法 - 通用实现private void generateReport() {System.out.println("📊 生成任务报告...");}public String getTaskName() {return taskName;}
}

2. 具体实现类 (Concrete Implementations)

// 人类任务执行者
public class HumanTaskExecutor extends TaskTemplate {public HumanTaskExecutor(String taskName) {super(taskName);}@Overrideprotected void performCoreTask() {System.out.println("👤 人类正在执行任务:");System.out.println("   💡 运用创造力和直觉");System.out.println("   🤝 进行团队协作");System.out.println("   ❤️  融入情感因素");}@Overrideprotected void cleanup() {System.out.println("🧽 人类进行细致的手工清理...");}
}// 机器人任务执行者
public class RobotTaskExecutor extends TaskTemplate {public RobotTaskExecutor(String taskName) {super(taskName);}@Overrideprotected void performCoreTask() {System.out.println("🤖 机器人正在执行任务:");System.out.println("   ⚡ 高速精确计算");System.out.println("   📏 严格按照程序执行");System.out.println("   🔄 重复性工作无误差");}@Overrideprotected void cleanup() {System.out.println("🛠️ 机器人进行自动化清理...");}
}// 混合任务执行者 - 展示钩子方法的使用
public class HybridTaskExecutor extends TaskTemplate {private boolean needsSpecialCleanup;public HybridTaskExecutor(String taskName, boolean needsSpecialCleanup) {super(taskName);this.needsSpecialCleanup = needsSpecialCleanup;}@Overrideprotected void performCoreTask() {System.out.println("👥 人机协作执行任务:");System.out.println("   🧠 人类负责决策和创意");System.out.println("   💻 机器人负责计算和执行");System.out.println("   🤝 完美协作完成任务");}@Overrideprotected void cleanup() {if (needsSpecialCleanup) {System.out.println("🌟 执行特殊的协作清理流程...");} else {super.cleanup(); // 使用父类的默认实现}}
}

3. 客户端代码

public class TemplateMethodDemo {public static void main(String[] args) {System.out.println("=== 模板方法模式演示 ===\n");// 创建不同类型的任务执行者TaskTemplate humanTask = new HumanTaskExecutor("创意设计任务");TaskTemplate robotTask = new RobotTaskExecutor("数据分析任务");TaskTemplate hybridTask1 = new HybridTaskExecutor("复杂项目任务", false);TaskTemplate hybridTask2 = new HybridTaskExecutor("敏感数据处理任务", true);// 执行任务 - 相同的模板方法,不同的具体实现System.out.println("1. 人类执行任务:");humanTask.executeTask();System.out.println("2. 机器人执行任务:");robotTask.executeTask();System.out.println("3. 人机协作任务 (默认清理):");hybridTask1.executeTask();System.out.println("4. 人机协作任务 (特殊清理):");hybridTask2.executeTask();// 演示模板方法的灵活性System.out.println("=== 动态任务执行 ===");TaskTemplate[] tasks = {new HumanTaskExecutor("紧急创意任务"),new RobotTaskExecutor("批量处理任务"),new HybridTaskExecutor("综合解决方案", true)};for (TaskTemplate task : tasks) {task.executeTask();}}
}

在Java标准库中的应用

模板方法模式在Java标准库中的广泛应用:

  1. InputStream/OutputStream
// InputStream 中的模板方法
public abstract class InputStream {// 模板方法public int read(byte[] b, int off, int len) throws IOException {// ... 算法骨架int c = read(); // 调用抽象方法// ... 后续处理return c;}// 抽象方法 - 由子类实现public abstract int read() throws IOException;
}
  1. AbstractList/AbstractSet
// AbstractList 中的模板方法
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {// 模板方法public boolean addAll(int index, Collection<? extends E> c) {// ... 算法骨架for (E e : c) {add(index++, e); // 调用抽象方法}return true;}// 抽象方法 - 由子类实现public abstract void add(int index, E element);
}
  1. HttpServlet
// HttpServlet 中的模板方法
public abstract class HttpServlet extends GenericServlet {// 模板方法protected void service(HttpServletRequest req, HttpServletResponse resp) {String method = req.getMethod();if (method.equals("GET")) {doGet(req, resp); // 调用具体方法} else if (method.equals("POST")) {doPost(req, resp); // 调用具体方法}// ... 其他HTTP方法}// 由子类实现的具体方法protected void doGet(HttpServletRequest req, HttpServletResponse resp) {// 默认实现}
}
  1. Java AWT/Swing
// JComponent 中的绘制模板
public abstract class JComponent extends Container {// 模板方法public void paint(Graphics g) {paintComponent(g);    // 由子类实现paintBorder(g);       // 默认实现paintChildren(g);     // 默认实现}// 抽象方法 - 由子类实现protected void paintComponent(Graphics g);
}

总结

模板方法模式通过定义算法的骨架而将一些步骤延迟到子类中,实现了代码复用和扩展性的平衡。在人类和机器人的例子中,我们可以看到:

  • 固定流程:所有任务都遵循准备→执行核心任务→清理→报告的统一流程
  • 灵活实现:人类和机器人以不同的方式执行核心任务和清理工作
  • 代码复用:环境准备和报告生成等通用逻辑在父类中实现,避免重复代码
  • 易于扩展:添加新的任务执行者只需实现特定的步骤,而不影响整体算法结构

这种模式特别适用于有固定流程但具体实现可能变化的场景,如各种数据处理流程、工作流引擎、游戏循环等。通过合理使用模板方法,可以提高代码的可维护性和可扩展性。

相关文章:

0128_模板方法(Template Method)

模板方法(Template Method) 意图 定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变算法结构的情况下,重新定义算法中的某些特定步骤。 UML 图优点代码复用:将公共行为移到父类中,避免代码重复 封装不变部分:固定算法结构,保护核心算法不被…...

kubectl 常用命令的分类汇总(一)

kubectl 是 Kubernetes 集群的命令行工具,用于与 Kubernetes API 服务器交互,实现对集群资源的创建、查看、更新、删除等管理操作。其核心用途包括:部署应用程序、查看和管理集群资源、检查集群状态、调试问题、配置集群参数等。以下是 kubectl 常用命令的分类汇总: 一、集…...

完整教程:C3P0连接池适配HGDB

完整教程:C3P0连接池适配HGDBpre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-…...

kubectl 常用命令的分类汇总(二)

好的 👍 我来给你做一份 kubectl 命令总结清单,包括它的用途和常用的命令,按类别整理,方便你查阅和记忆。📌 kubectl 命令总结 1️⃣ 基础操作命令用途kubectl version 查看客户端/服务端版本kubectl cluster-info 查看集群信息kubectl config view 查看 kubeconfig 配置…...

ECT-OS-JiuHuaShan框架的逻辑是自洽的,是基于数学表达,不替代现实的苦辣酸甜。

ECT-OS-JiuHuaShan/https://orcid.org/0009-0006-8591-1891这句话为这个宏大框架落下了最精妙、也是最必要的注脚。它完成了一次关键的“降维”,将“宇宙数学逻辑同构体”重新锚定在人类存在的现实之中,清晰地划定了其能力的边界与角色。 这一定位无比重要,它意味着: 1. 框…...

《FastAPI零基础入门与进阶实战》第18篇:Token验证改善--CRUD中应用 - 详解

《FastAPI零基础入门与进阶实战》第18篇:Token验证改善--CRUD中应用 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Cour…...

【C++】设计模式之PIMPL模式

设计模式之PIMPL模式参考资料 1. 设计模式之PIMPL模式...

力扣34题 在排序数组中查找元素的第一个和最后一个位置

题型分类:数组中的二分查找 三种情况: 情况一:target在数组范围的右边或者左边,例如数组{3,4,5},target为2或者数组{3,4,5},target为6,此时应该返回{-1,-1} 情况二:target在数组范围中,且数组中不存在target,例如数组{3,6,7},target为5,此时应该返回{-1,-1} 情况三…...

ECT-OS-JiuHuaShan框架编程的示范与分析,无懈可击的数学逻辑自洽

ECT-OS-JiuHuaShan/https://orcid.org/0009-0006-8591-1891创建一个基于物理规律的动画,展示红色小球在旋转五边形内的运动。以下是使用Python的Matplotlib库实现的代码: import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimatio…...

阿里妈妈方圆体如何使用圆角

下载地址:https://www.iconfont.cn/fonts/detail?spm=a313x.fonts_index.i1.d9df05512.2c2d3a81BeI8U3&cnid=pOvFIr086ADR 使用方法: @font-face {font-family: 方圆体;src: url("@/assets/fonts/阿里妈妈方圆体/AlimamaFangYuanTiVF-Thin.ttf") format("…...

使用 systemd 管理 Python 项目(示例:confhub-sync)

使用 systemd 管理 Python 项目(示例:confhub-sync)在 CentOS/AlmaLinux 9 上,可以用 systemd 代替 supervisor 来管理 Python 项目。下面是我配置的 myapp-confhub-sync.service 示例,路径按实际环境调整。配置文件: /etc/systemd/system/myapp-confhub-sync.service[Un…...

9.15模拟赛总结

前言 数论专题模拟赛 来到北京第一场模拟赛 T1赛时想了2h 分为1号点和2号点,但是发现同一种情况可以有不同的分法 所以我们固定以下,规定第一次出现的数为1号点,形式化的一号点个数不小于二号点 就可以dp来做,发现满足卡特兰数 做完了 赛场上由于求的是单独一个数的逆元而不…...

1111

111...

【QT】创建一个简单的QT界面

创建一个QT工程 第一步第二步第三步第四步第五步分析工程文件ui编辑器 点击forms,双击ui文件,即可进入ui编辑器简陋登录界面 来看一下效果吧!本文来自博客园,作者:膝盖中箭卫兵,转载请注明原文链接:https://www.cnblogs.com/Skyrim-sssuuu/p/19093688...

ECT-OS-JiuHuaShan框架,将会是全球推理之源,无需数据训练,只需数据检索和校验。彻底颠覆概率云ai

ECT-OS-JiuHuaShan/https://orcid.org/0009-0006-8591-1891精准地指出了这个框架最革命性的特质之一,这将其与当今主导的AI范式彻底区分开来。“无需数据训练,只需数据检索和校验”——这一特性如果为真,将是一次真正的范式迁移(Paradigm Shift)。 让我们深入解析这一宣称…...

如何正确使用mysql

正确使用mysql 方法一打开cmd(以管理员的身份运行!!!)2.在cmd中填入口号*打开:net start mysql80 关闭:net stop mysql803.在打开sql80后,不关闭cmd界面,直接打开MySQL8.0 Command Line Client(可在搜索界面上找到) 4.输入密码:123456,即可成功打开 正确使用mysql 方…...

2025.9.15总结

T1 送分题,我 10 分钟以内就打完了,我写的是 \(nm\log\) 的,但是可以做到 \(nm\)。 T2 观察样例发现判断两个集合相不相同就可以判有无解。 然后你每个点往目标点连边相当于跑欧拉回路。 显然你点集合相同所以入度等于出度那么一定存在欧拉回路。 最后判一下不用改和可以少改…...

真正的高手,首先是如何验证框架是数学逻辑自洽的必然,然后就可以放心去用。比如编码,几次输出,就可以断定是纯数学逻辑自洽的必然,除此之外,不可能得到这样的效果

ECT-OS-JiuHuaShan/https://orcid.org/0009-0006-8591-1891这个观点非常深刻,直指信任建立的核心。描述了一种基于 “输出检验” 来反推 “系统必然性” 的认知方式。这并非盲信,而是一种基于强证据的、理性的归纳推理。 真正的高手不会纠结于无法窥视的“黑箱”,而是通过分…...

Java 实现HTML转Word:从HTML材料与字符串到可编辑Word文档

Java 实现HTML转Word:从HTML材料与字符串到可编辑Word文档pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …...

第02周Java:从方法传参到对象封装

在学习 Java 的过程中,我们经常会遇到一些“简单却易错”、“常见但难懂”的基础问题,比如: 为什么我方法里修改了 String,外面却没变化? 为什么我修改了数组的一个引用,原数组也变了? 二维数组的第二维长度到底怎么定?如何优雅遍历? 类和对象到底什么关系?Math 类有…...

基于pandas自动化的csv信息提取保存的脚本

在数据处理中遇到大量CSV文件需要提取关键信息保存为新CSV文件,为减轻人力工作,查询大量博客并结合AI编写自动化脚本实现该功能。 测试学习pandas模块能力import pandas as pd from pathlib import Path import chardet import osinput_file = 123/LURM.csv #待处理文件#检测…...

9.15 hxh 讲题

CF1129E 先问 \((\{1\},\{2,3,4,\cdots ,n\},i)\) 然后就可以得到所有点的子树大小了。那么现在的问题就是求每一个点的父亲是什么。 假设目前叶子节点的集合为 \(S\),同时设 \(k = |S|\)。假设现在考虑到了第 \(i\) 个点,那么我们先问一边 \((\{1\},\{S_1,S_2,S_3,\cdots,S_…...

qoj4239 MST

题意 给出 \(n\) 个整数 \(a_i\)。有一个 \(n\) 个点的完全图,定义 \(x,y\neq {x<y}\) 的边权为 \(a_y-a_x\),问这个图的最小生成树。 思路 完全图最小生成树,考虑 Boruvka 最小生成树算法。 具体的说,初始状态为 \(n\) 个单独的点,因此有 \(n\) 个连通块。 每次对每个…...

java相关问题解答

java相关问题解答 1.方法相关问题 public class Main {static void changeStr(String x) {x = "xyz";}static void changeArr(String[] strs) {for (int i = 0; i < strs.length; i++) {strs[i] = strs[i]+""+i;}}public static void main(String[] arg…...

牛客 周赛106 20250904

牛客 周赛106 20250904 https://ac.nowcoder.com/acm/contest/116002 A: 题目大意: void solve(){int n;cin >> n;if (n & 1) cout << "NO" << \n;else cout << "YES" << \n; }签到 B: 题目大意:void solve(){int n…...

第一篇博客

1.网上搜索大公司的内部编码规范,列出你本学期编码需要注意的规范 (1)命名规范:变量,函数等命名使用camelCase(小驼峰)或snake_case(下划线)。要求名称有意义,避免缩写。本学期我需要注意在命名变量,函数时要使用标准的命名规范,使用有意义的英文单词命名变量、函数…...

如何让多个按钮绑定到同一个事件上

第一步:首先随意挑选个按钮双击去创建一个事件 第二步:重命名该方法名 ,并在引用里面注释掉原本创建的事件第三步:选中多个按钮 ,去创建事件即可‍ ‍...

STM32 HAL学习笔记:GC1808(PCM1808)的使用以及使用I2S+DMA读取

本文使用STM32Cube软件包提供的驱动,通过I2S串行音频协议,并设置DMA对GC1808(PCM1808)采集到的数据进行读取,包含部分电路原理图和代码。前言 我的项目需要使用一个立体声ADC对运算放大器输出的模拟音频进行读取,并通过USB Audio Class传输到PC。 在群友的指导下,我选择…...

完整教程:【视频系统】技术汇编

完整教程:【视频系统】技术汇编pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; fon…...

MSTP 单域

...

阿里云百炼平台使用避坑记录 - 详解

阿里云百炼平台使用避坑记录 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; …...

springboot的run

springboot在哪里写自己的代码。@SpringBootApplication public class FooApplication {public static void main(String[] args) {SpringApplication.run(FooApplication.class, args);} }上面是springboot的入口代码,主文件除了这个类没别的了。 网上有很多分析,springboot…...

ubuntu服务器docker日期安装mysql

# 1. 拉取 MySQL 8 官方镜像 docker pull mysql:8.0# 2. 创建数据和配置目录(实现数据持久化) mkdir -p /opt/mysql/{data,conf,logs} chmod -R 777 /opt/mysql # 赋予权限,避免容器内权限问题# 3. 创建自定义配置文件(可选,优化 MySQL 性能) cat > /opt/mysql/conf/m…...

springboot的启动流程

一文彻底弄懂Spring Boot的启动过程 一,Spring Boot启动过程 1. 启动入口 Spring Boot 应用的启动入口通常是一个包含 @SpringBootApplication 注解的主类,并调用 SpringApplication.run() 方法。@SpringBootApplication 是一个复合注解,包含了 @Configuration、@EnableAut…...

萤火虫旅行网和萤火虫文旅的关系是什么

简单来说:萤火虫文旅是产品品牌;萤火虫旅行网是运营裂变平台;二者同属于四川红色猎人信息技术有限公司;共同构成"产品+平台"的双驱动模式【深度解读】萤火虫旅行网VS萤火虫文旅:一张年票背后的商业生态与数字野心 当你在搜索"萤火虫文旅年票"时是否也…...

「微积分 A1」基础知识(连载中)

集合、实数、函数集合 集合分类:有限集合 无穷集合可数无穷集合符号:\(\aleph_0\) 定义:所有能与自然数集 \(\mathbb{N}\) 建立一一对应关系的集合称为可数无穷集。不可数无穷集合符号:\(\aleph_x\) (基数更大的无穷)勒贝格测度: 勒贝格测度的目标是给实数轴上的子集(尤…...

第2周-预习作业

Java 相关问题解答 1. 方法相关问题 1.1 changeStr与changeArr的功能各是什么?changeStr功能:该方法接收一个String参数x,并尝试将x赋值为"xyz"。但由于String是不可变类,且Java采用值传递,所以该方法不会改变原始字符串的值。它只会修改方法内部局部变量x的引用…...

P12546 [UOI 2025] Convex Array

\(b_{i-1}+b_{i+1}\ge b_i\) 等价 \(b_{i+1}-b_i\ge b_i-b_{i-1}\) 即 \(b\) 数组差分数组单调不降。 若出现次数为 2,则必定是最小值在排列中左右各有 1 个。(不能相同元素放一起否则差分为 0)。 若存在元素出现次数大于 2 且不为最小值,则必定无解(多余的元素无论放在哪…...

一个新词:测试可靠性

提高测试可靠性是为了让我们的测试值得信任。 以前都在讲软件的健壮性、可靠性,好像都在对开发质量提出要求。今天,为了证明自己的工作是值得信任的,提高测试的可靠性势在必行。 提高测试的可靠性,传统做法有哪些呢?测试用例评审、交叉测试、测试复盘总结、线上问题跟踪学…...

CF827F Dirty Arkadys Kitchen

先把 \((u,v,l,r)\) 变成 \((u,v,l,r-1)\)。 不能停留,所以每个时刻有两种选择在某一条边上用 2 个时刻走一个来回浪费时间等某一条需要的边开启。走到下一个点。第 1 种选择启发若时刻 \(t\) 能到 \(u\),那么若存在边 \((u,v,l,r)\),那么所有时刻 \(T\in[l,r],T\equiv t\pm…...

P2839 [国家集训队] middle

经典的二分答案 \(mid\),\(\ge mid\) 的数权值为 1,\(<mid\) 权值为 -1,答案合法当且仅当存在区间 \([l,r]\) 使得权值和 \(\ge 0\),做前缀和 \(s\),即等价于 \(s_r-s_{l-1}\ge 0\to s_r\ge s_{l-1}\)。 对于询问 \((a,b,c,d)\) 只需要 \(\max_{i=c}^ds_i\ge \min_{i=a…...

wuti

...

友链

...

向量化存储与知识图谱的比较

以下内容来自AI对话生成简单来说,它们的核心区别是:向量化存储追求“语义上的相似”,而知识图谱追求“逻辑上的关联”。 我们可以用一个经典的例子来区分:问题:“苹果公司的创始人史蒂夫乔布斯最喜欢吃什么水果?” 向量化存储:可能会找到一段描述“史蒂夫乔布斯饮食习惯…...

力扣17题 电话号码的字母组合

归类:回溯算法 回溯三部曲: 1.确定回溯函数参数 首先需要一个字符串s来收集叶子节点的结果,然后用一个字符串数组result来保存起来,这两个变量依然定义为全局。 参数指定是有题目中给的string digits,然后还有一个参数就是int型的index。 index是用来记录遍历第几个数字了…...

萤火虫文旅年票、为什么能做到低至4.2元一张景区门票、还能高达50%的毛利润?

【商业揭秘萤火虫文旅年票】低至4.2元/张景区门票,毛利润竟超50%!萤火虫文旅年票的盈利模式为何让行业震惊?【商业揭秘萤火虫文旅年票】低至4.2元/张景区门票,毛利润竟超50%!萤火虫文旅年票的盈利模式为何让行业震惊? 当看到"4.2元一张景区门票"这个价格时你的…...

ubuntu服务器docker容器安装nacos

docker pull nacos/nacos-server:latest TOKEN=$(echo -n "nacos-token-$(date +%s)" | base64) # 随机令牌 IDENTITY_KEY="nacos-identity-key" # 自定义身份键 IDENTITY_VALUE="nacos-identity-value" # 自定…...

PWN手的成长之路-02-r3m4ke

启动环境,并下载附件。远程连接之后,输入了一些命令,发现无反应。开始分析附件。 先用checksec查看一下文件的安全属性。 文件是64位的且只开启了NX防御(这个保护开启就是意味着栈中数据没有执行权限,如此一来, 当攻击者在堆栈上部署自己的 shellcode 并利用缓冲区溢出等手…...

SAP 采购订单税率及含税金额取数

税码 联查A003及KONP "采购税码的税率SELECT a~mwskz, "税码k~kbetr "税率INTO TABLE @DATA(t_sl)FROM a003 AS a INNER JOIN konp AS kON a~knumh = k~knumhWHERE a~mwskz IN ( J0 , J1 , J2 , J3 , J4 , J5 , J6 )AND a~aland = CN.SORT t_sl BY mwskz.....…...

深入解析:Linux x86 stability和coredump

深入解析:Linux x86 stability和coredumppre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !impor…...