模板方法模式:定义算法的骨架

摘要

模板方法模式(Template Method Pattern)是行为型设计模式中的"算法架构师",它在父类中定义算法的骨架,将具体步骤延迟到子类实现。本文将深入探讨模板方法模式的核心概念、实现方式、应用场景及高级变体,通过丰富的Java代码示例展示如何构建可扩展的算法框架,并分析其与策略模式、工厂方法模式的区别与适用场景。

一、模板方法模式核心思想

模板方法模式的核心是定义算法骨架,延迟具体步骤实现,具有以下关键特征:

  1. 算法框架固定:在父类中定义不可变的算法流程
  2. 步骤延迟实现:具体步骤由子类实现
  3. 钩子方法支持:提供可选扩展点控制流程
  4. 避免重复代码:公共行为在父类中实现

适用场景:

  • 多个算法有相同流程但不同实现细节
  • 需要控制子类扩展点
  • 重构重复代码到父类
  • 框架设计中的生命周期控制

二、模板方法模式结构解析

UML类图示意

[AbstractClass] <|-- [ConcreteClass]
[AbstractClass] : +templateMethod()
[AbstractClass] : +primitiveOperation1()
[AbstractClass] : +primitiveOperation2()
[ConcreteClass] : +primitiveOperation1()
[ConcreteClass] : +primitiveOperation2()

核心组件角色

角色 职责 典型实现
AbstractClass 抽象类 定义模板方法和基本方法
ConcreteClass 具体子类 实现抽象类中的抽象方法
Template Method 模板方法 定义算法骨架
Primitive Method 基本方法 抽象方法或具体方法

三、基础实现:数据导出案例

// 抽象模板类
abstract class DataExporter {// 模板方法(final防止子类覆盖)public final void exportData() {connectToDataSource();retrieveData();processData();if (needFormatting()) {formatData();}saveData();disconnect();}// 具体方法(已有默认实现)private void connectToDataSource() {System.out.println("Connecting to data source...");}private void disconnect() {System.out.println("Disconnecting from data source...");}// 抽象方法(必须由子类实现)protected abstract void retrieveData();protected abstract void processData();protected abstract void saveData();// 钩子方法(可选覆盖)protected boolean needFormatting() {return false;}protected void formatData() {// 默认空实现}
}// 具体实现:CSV导出
class CsvExporter extends DataExporter {@Overrideprotected void retrieveData() {System.out.println("Retrieving data for CSV export");}@Overrideprotected void processData() {System.out.println("Processing data for CSV format");}@Overrideprotected void saveData() {System.out.println("Saving data to CSV file");}@Overrideprotected boolean needFormatting() {return true;}@Overrideprotected void formatData() {System.out.println("Formatting data with CSV specifications");}
}// 具体实现:PDF导出
class PdfExporter extends DataExporter {@Overrideprotected void retrieveData() {System.out.println("Retrieving data for PDF export");}@Overrideprotected void processData() {System.out.println("Processing data for PDF layout");}@Overrideprotected void saveData() {System.out.println("Saving data to PDF document");}
}// 客户端使用
public class ExportClient {public static void main(String[] args) {DataExporter csvExporter = new CsvExporter();csvExporter.exportData();System.out.println("\n---\n");DataExporter pdfExporter = new PdfExporter();pdfExporter.exportData();}
}

四、高级应用:框架生命周期控制

1. Spring框架中的模板方法

// Spring的JdbcTemplate是模板方法的经典实现
public class JdbcTemplate {public <T> T query(String sql, ResultSetExtractor<T> rse) {// 模板方法流程:// 1. 获取连接// 2. 创建语句// 3. 执行查询// 4. 处理结果集(由rse实现)// 5. 关闭资源}
}// 使用示例
public class EmployeeDao {private JdbcTemplate jdbcTemplate;public Employee getEmployeeById(long id) {return jdbcTemplate.query("SELECT * FROM employees WHERE id = ?",new Object[]{id},(rs, rowNum) -> {Employee emp = new Employee();emp.setId(rs.getLong("id"));emp.setName(rs.getString("name"));emp.setDepartment(rs.getString("department"));return emp;});}
}

2. Hibernate DAO模板

public class HibernateTemplate {public <T> T execute(HibernateCallback<T> action) {// 模板方法流程:// 1. 获取Session// 2. 开启事务// 3. 执行回调// 4. 提交事务// 5. 异常处理// 6. 关闭Session}
}// 使用示例
List<User> users = hibernateTemplate.execute(session -> session.createQuery("FROM User", User.class).list()
);

五、模板方法模式优缺点分析

优点:

优点 说明
代码复用 公共代码在父类中实现
扩展性好 新增子类不影响现有代码
控制反转 父类控制算法流程
符合开闭原则 对扩展开放,对修改关闭

缺点:

缺点 说明
类数量增加 每个实现需要一个子类
设计复杂度 需要合理设计抽象方法
继承限制 只能通过继承扩展
父类变化影响 父类修改影响所有子类

六、模板方法模式与其他模式对比

模板方法 vs 策略模式

维度 模板方法模式 策略模式
实现方式 继承 组合
算法控制 父类控制流程 客户端选择策略
扩展性 通过子类扩展 通过新策略扩展
适用场景 算法骨架固定 算法整体可变

模板方法 vs 工厂方法模式

维度 模板方法模式 工厂方法模式
目的 定义算法骨架 创建对象
关注点 算法步骤 对象创建
方法类型 模板方法包含多个步骤 工厂方法只负责创建
典型应用 框架生命周期 对象创建解耦

七、模板方法模式最佳实践

1. 钩子方法高级应用

abstract class Game {// 模板方法final void play() {initialize();startPlay();if (allowCheats()) {enableCheats();}endPlay();showScore();}abstract void initialize();abstract void startPlay();abstract void endPlay();// 钩子方法boolean allowCheats() {return false; // 默认不允许作弊}void enableCheats() {// 默认空实现}void showScore() {System.out.println("Showing default score display");}
}class ChessGame extends Game {void initialize() {System.out.println("Setting up chess board");}void startPlay() {System.out.println("Starting chess game");}void endPlay() {System.out.println("Checkmate! Game over");}// 覆盖钩子方法boolean allowCheats() {return true; // 国际象棋允许特定"作弊"}void enableCheats() {System.out.println("Enabling chess engine assistance");}void showScore() {System.out.println("Displaying chess rating points");}
}

2. 模板方法模式与函数式接口结合

class FunctionalTemplate {public void executeTemplate(Runnable preProcess,Runnable mainProcess,Runnable postProcess) {preProcess.run();try {mainProcess.run();} finally {postProcess.run();}}
}// 使用示例
FunctionalTemplate template = new FunctionalTemplate();
template.executeTemplate(() -> System.out.println("Setup resources"),() -> System.out.println("Core business logic"),() -> System.out.println("Cleanup resources")
);

八、模板方法模式在开源框架中的应用

JUnit测试框架

public abstract class TestCase {public void runBare() throws Throwable {setUp();try {runTest();} finally {tearDown();}}protected void setUp() throws Exception {}protected void tearDown() throws Exception {}protected void runTest() throws Throwable {// 反射调用测试方法}
}

Java AWT中的模板方法

public abstract class Component {public void paint(Graphics g) {if (peer != null) {peer.paint(g);}}// 其他模板方法...
}

九、高级应用:分布式事务模板

abstract class DistributedTransactionTemplate {public final void executeTransaction() {try {beginTransaction();executeBusinessLogic();commitTransaction();} catch (Exception e) {rollbackTransaction();handleError(e);} finally {cleanupResources();}}private void beginTransaction() {System.out.println("Starting distributed transaction");}private void commitTransaction() {System.out.println("Committing transaction");}private void rollbackTransaction() {System.out.println("Rolling back transaction");}private void cleanupResources() {System.out.println("Cleaning up resources");}protected abstract void executeBusinessLogic() throws Exception;protected void handleError(Exception e) {System.err.println("Transaction failed: " + e.getMessage());}
}// 具体实现
class OrderProcessingTransaction extends DistributedTransactionTemplate {protected void executeBusinessLogic() throws Exception {System.out.println("Processing order business logic");// 复杂的业务逻辑if (Math.random() > 0.5) {throw new Exception("Simulated business error");}}@Overrideprotected void handleError(Exception e) {super.handleError(e);notifyAdmin(e);}private void notifyAdmin(Exception e) {System.out.println("Notifying admin about failure");}
}

十、模板方法模式未来发展趋势

新兴应用方向:

  1. 云原生应用:跨服务事务模板
  2. 微服务编排:服务调用流程模板
  3. Serverless架构:函数执行模板
  4. AI工作流:机器学习流程模板
  5. 区块链智能合约:交易处理模板

响应式模板方法

// Reactor中的模板方法应用
Mono<Void> reactiveTemplate = Mono.fromRunnable(this::preProcess).then(Mono.defer(this::mainProcess)).doOnError(this::handleError).then(Mono.fromRunnable(this::postProcess));reactiveTemplate.subscribe();

总结

模板方法模式是构建可复用算法框架的基石,特别适合需要固定流程但允许步骤变化的场景。其核心价值体现在:

  1. 算法复用:公共流程在父类中实现
  2. 扩展灵活:子类可定制特定步骤
  3. 控制反转:父类控制流程,子类实现细节
  4. 框架基础:为复杂系统提供标准生命周期

现代应用关键点:

  • 合理设计抽象方法:平衡父类控制和子类自由
  • 钩子方法运用:提供灵活扩展点
  • 避免过度抽象:防止过度设计导致复杂度增加
  • 与函数式编程结合:使用Lambda简化实现
  • 异常处理:完善模板中的错误处理机制

模板方法模式正在与响应式编程、云原生架构等现代技术结合,演进出更强大的流程控制能力。掌握模板方法模式的精髓,将帮助开发者构建出更加健壮、可扩展的系统架构,特别是在框架设计和复杂流程管理领域。