模板方法模式:算法骨架的优雅封装
摘要
模板方法模式是行为型设计模式中的"算法架构师",它在父类中定义算法的骨架,将具体步骤延迟到子类实现。本文将深入探讨模板方法模式的核心思想、实现方式、应用场景及高级变体,通过丰富的Java代码示例展示如何构建可扩展的算法框架,并分析其与策略模式、回调模式的区别与适用场景。
一、模板方法模式核心思想
模板方法模式的核心是定义算法骨架,延迟具体步骤实现,具有以下关键特征:
- 算法框架固定:在父类中定义不可变的算法流程
- 步骤延迟实现:具体步骤由子类实现
- 钩子方法支持:提供可选扩展点控制流程
- 避免重复代码:公共行为在父类中实现
适用场景:
- 多个算法有相同流程但不同实现细节
- 需要控制子类扩展点
- 重构重复代码到父类
- 框架设计中的生命周期控制
二、模板方法模式结构解析
UML类图示意
[AbstractClass] <|-- [ConcreteClass]
[AbstractClass] : +templateMethod()
[AbstractClass] : +primitiveOperation1()
[AbstractClass] : +primitiveOperation2()
[ConcreteClass] : +primitiveOperation1()
[ConcreteClass] : +primitiveOperation2()
核心组件角色
角色 | 职责 | 典型实现 |
---|---|---|
AbstractClass | 定义算法骨架 | 抽象类包含模板方法和基本方法 |
ConcreteClass | 实现具体步骤 | 继承抽象类,实现抽象方法 |
Template Method | 算法骨架 | final方法定义流程 |
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 {
@Override
protected void retrieveData() {
System.out.println("Retrieving data for CSV export");
}
@Override
protected void processData() {
System.out.println("Processing data for CSV format");
}
@Override
protected void saveData() {
System.out.println("Saving data to CSV file");
}
@Override
protected boolean needFormatting() {
return true;
}
@Override
protected void formatData() {
System.out.println("Formatting data with CSV specifications");
}
}
// 具体实现:PDF导出
class PdfExporter extends DataExporter {
@Override
protected void retrieveData() {
System.out.println("Retrieving data for PDF export");
}
@Override
protected void processData() {
System.out.println("Processing data for PDF layout");
}
@Override
protected 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();
}
}
四、高级应用:框架生命周期控制
Spring框架中的模板方法应用
// Spring的JdbcTemplate是模板方法的经典实现
public class EmployeeDao {
private JdbcTemplate jdbcTemplate;
public Employee getEmployeeById(long id) {
return jdbcTemplate.queryForObject(
"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;
}
);
}
}
// 内部实现原理
public class JdbcTemplate {
public <T> T query(String sql, ResultSetExtractor<T> rse) {
// 模板方法流程:
// 1. 获取连接
// 2. 创建语句
// 3. 执行查询
// 4. 处理结果集(由rse实现)
// 5. 关闭资源
}
}
五、模板方法模式变体
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. 模板方法链
abstract class PaymentProcessor {
// 主模板方法
public final void processPayment(double amount) {
validatePayment(amount);
executePayment(amount);
if (isInternational()) {
handleCurrencyConversion(amount);
}
sendConfirmation();
}
abstract void validatePayment(double amount);
abstract void executePayment(double amount);
// 钩子方法
boolean isInternational() {
return false;
}
void handleCurrencyConversion(double amount) {
// 默认实现
}
void sendConfirmation() {
System.out.println("Sending standard payment confirmation");
}
}
abstract class OnlinePaymentProcessor extends PaymentProcessor {
@Override
final void validatePayment(double amount) {
checkFraudDetection();
checkAccountBalance(amount);
}
abstract void checkAccountBalance(double amount);
void checkFraudDetection() {
System.out.println("Running standard fraud detection");
}
}
class CreditCardProcessor extends OnlinePaymentProcessor {
void checkAccountBalance(double amount) {
System.out.println("Checking credit limit for $" + amount);
}
void executePayment(double amount) {
System.out.println("Processing credit card payment for $" + amount);
}
@Override
void sendConfirmation() {
System.out.println("Sending email and SMS confirmation");
}
}
六、模板方法模式在框架中的应用
1. Servlet生命周期
public abstract class HttpServlet extends GenericServlet {
// 模板方法
public void service(HttpServletRequest req, HttpServletResponse res) {
String method = req.getMethod();
if (method.equals("GET")) {
doGet(req, res);
} else if (method.equals("POST")) {
doPost(req, res);
}
// 其他HTTP方法...
}
// 基本方法(由子类实现)
protected void doGet(HttpServletRequest req, HttpServletResponse res) {
// 默认实现返回405错误
}
protected void doPost(HttpServletRequest req, HttpServletResponse res) {
// 默认实现返回405错误
}
}
// 自定义Servlet实现
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res) {
// 处理GET请求
}
}
2. 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 {
// 反射调用测试方法
}
}
// 自定义测试用例
public class MyTest extends TestCase {
@Override
protected void setUp() {
// 初始化测试环境
}
public void testSomething() {
// 测试逻辑
}
}
七、模板方法模式与策略模式对比
维度 | 模板方法模式 | 策略模式 |
---|---|---|
目的 | 定义算法骨架 | 封装可互换算法 |
实现方式 | 继承 | 组合 |
扩展点 | 子类重写方法 | 替换策略对象 |
控制粒度 | 算法步骤级别 | 整个算法级别 |
运行时变化 | 编译时确定 | 运行时可切换 |
适用场景 | 算法结构固定 | 算法整体可变 |
八、模板方法模式最佳实践
1. 保护模板方法
public abstract class SecureTemplate {
// 使用final保护模板方法
public final void executeProcess() {
authenticate();
doProcess();
logAction();
}
private void authenticate() {
// 统一认证逻辑
}
private void logAction() {
// 统一日志记录
}
protected abstract void doProcess();
}
2. 模板方法与函数式接口结合(Java 8+)
public class FunctionalTemplate {
public void executeTemplate(
Runnable preProcess,
Runnable mainProcess,
Runnable postProcess
) {
preProcess.run();
try {
mainProcess.run();
} finally {
postProcess.run();
}
}
}
// 使用示例
new FunctionalTemplate().executeTemplate(
() -> System.out.println("Setup resources"),
() -> System.out.println("Core business logic"),
() -> System.out.println("Cleanup resources")
);
3. 模板方法工厂
abstract class ReportGenerator {
public final Report generateReport() {
Report report = createReport();
gatherData(report);
analyzeData(report);
formatReport(report);
return report;
}
protected abstract Report createReport();
protected abstract void gatherData(Report report);
protected abstract void analyzeData(Report report);
protected abstract void formatReport(Report report);
}
class FinancialReportGenerator extends ReportGenerator {
protected Report createReport() {
return new FinancialReport();
}
protected void gatherData(Report report) {
// 获取财务数据
}
// ...其他方法实现
}
class ReportGeneratorFactory {
public static ReportGenerator createGenerator(ReportType type) {
switch (type) {
case FINANCIAL: return new FinancialReportGenerator();
case SALES: return new SalesReportGenerator();
default: throw new IllegalArgumentException();
}
}
}
九、高级应用:分布式事务模板
public 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");
}
}
@Override
protected void handleError(Exception e) {
super.handleError(e);
notifyAdmin(e);
}
private void notifyAdmin(Exception e) {
System.out.println("Notifying admin about failure");
}
}
十、模板方法模式在开源框架中的应用
1. Spring JMS模板
public class JmsTemplate {
public <T> T execute(SessionCallback<T> action) {
// 模板方法流程:
// 1. 获取连接
// 2. 创建会话
// 3. 执行回调(由action实现)
// 4. 处理异常
// 5. 释放资源
}
}
// 使用示例
jmsTemplate.execute(session -> {
MessageProducer producer = session.createProducer(queue);
TextMessage message = session.createTextMessage("Hello");
producer.send(message);
return null;
});
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()
);
总结
模板方法模式是构建可扩展框架的基石,它通过固定算法骨架、延迟具体实现的方式,完美平衡了结构稳定性与实现灵活性。该模式的核心价值体现在:
- 架构控制:确保算法流程符合规范
- 代码复用:消除重复代码,提高可维护性
- 扩展可控:通过钩子方法提供安全扩展点
- 框架基础:为复杂系统提供标准生命周期管理
应用关键点:
- 识别稳定流程:确定算法中不变的部分
- 设计扩展点:合理使用抽象方法和钩子方法
- 保护模板:使用final防止骨架被破坏
- 平衡灵活性:避免过度设计导致复杂度增加
在现代开发中,模板方法模式正与函数式编程结合,演变为更灵活的"模板函数"形式。理解并掌握这一模式,将帮助开发者设计出更健壮、更易扩展的系统架构,特别是在框架设计和复杂业务流程管理领域。