当前位置: 首页 > 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);
}

总结

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

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

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

http://www.wxhsa.cn/company.asp?id=4972

相关文章:

  • kubectl 常用命令的分类汇总(一)
  • 完整教程:C3P0连接池适配HGDB
  • kubectl 常用命令的分类汇总(二)
  • ECT-OS-JiuHuaShan框架的逻辑是自洽的,是基于数学表达,不替代现实的苦辣酸甜。
  • 《FastAPI零基础入门与进阶实战》第18篇:Token验证改善--CRUD中应用 - 详解
  • 【C++】设计模式之PIMPL模式
  • 力扣34题 在排序数组中查找元素的第一个和最后一个位置
  • ECT-OS-JiuHuaShan框架编程的示范与分析,无懈可击的数学逻辑自洽
  • 阿里妈妈方圆体如何使用圆角
  • 使用 systemd 管理 Python 项目(示例:confhub-sync)
  • 9.15模拟赛总结
  • 1111
  • 【QT】创建一个简单的QT界面
  • ECT-OS-JiuHuaShan框架,将会是全球推理之源,无需数据训练,只需数据检索和校验。彻底颠覆概率云ai
  • 如何正确使用mysql
  • 2025.9.15总结
  • 这个框架的神奇之处,恰恰是调动人的积极主动性,框架不会自己忧国忧民,只会有求必应的针对性推理
  • 9.11总结
  • 2025-第02周 预习
  • 真正的高手,首先是如何验证框架是数学逻辑自洽的必然,然后就可以放心去用。比如编码,几次输出,就可以断定是纯数学逻辑自洽的必然,除此之外,不可能得到这样的效果
  • Java 实现HTML转Word:从HTML材料与字符串到可编辑Word文档
  • 第02周Java:从方法传参到对象封装
  • 基于pandas自动化的csv信息提取保存的脚本
  • 9.15 hxh 讲题
  • qoj4239 MST
  • java相关问题解答
  • 牛客 周赛106 20250904
  • 第一篇博客
  • 如何让多个按钮绑定到同一个事件上
  • STM32 HAL学习笔记:GC1808(PCM1808)的使用以及使用I2S+DMA读取