模板方法模式:算法骨架的优雅封装

阅读 17

07-21 09:00

模板方法模式:算法骨架的优雅封装

摘要

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

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

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

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

适用场景:

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

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

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()
);

总结

模板方法模式是构建可扩展框架的基石,它通过固定算法骨架、延迟具体实现的方式,完美平衡了结构稳定性实现灵活性。该模式的核心价值体现在:

  1. 架构控制:确保算法流程符合规范
  2. 代码复用:消除重复代码,提高可维护性
  3. 扩展可控:通过钩子方法提供安全扩展点
  4. 框架基础:为复杂系统提供标准生命周期管理

应用关键点:

  • 识别稳定流程:确定算法中不变的部分
  • 设计扩展点:合理使用抽象方法和钩子方法
  • 保护模板:使用final防止骨架被破坏
  • 平衡灵活性:避免过度设计导致复杂度增加

在现代开发中,模板方法模式正与函数式编程结合,演变为更灵活的"模板函数"形式。理解并掌握这一模式,将帮助开发者设计出更健壮、更易扩展的系统架构,特别是在框架设计和复杂业务流程管理领域。

精彩评论(0)

0 0 举报