Spring + 设计模式 (十五) 行为型 - 模板方法模式

模板方法模式

引言

模板方法模式是一种行为型设计模式,定义了一个操作的骨架,将具体步骤延迟到子类实现。它的核心是通过抽象类或接口固定算法的总体流程,同时允许子类在不改变结构的情况下定制部分步骤。就像烹饪一道菜:模板方法给出"炒菜"的通用步骤(热锅、放油、翻炒),具体食材和调料由子类决定。在企业开发中,模板方法模式常用于流程化操作,如数据处理、事务管理、请求处理等场景,兼顾代码复用和灵活性。它的魅力在于既保证了流程的稳定性,又给子类留足发挥空间。

实际开发中的用途

模板方法模式适合需要统一流程但部分步骤可定制的场景。比如,批量数据导入系统:无论导入用户数据还是订单数据,流程都是"读取文件 → 校验数据 → 持久化",但具体校验和持久化逻辑因数据类型不同。模板方法模式通过抽象类定义通用流程,子类实现差异化步骤,避免重复代码。

举个例子:开发一个报表生成系统,报表有多种类型(如PDF、Excel),但生成流程一致:加载数据 → 格式化 → 导出文件。用模板方法模式,抽象类定义流程,子类实现格式化和导出的具体逻辑。如果要加个新报表类型(比如CSV),只写个新子类,流程代码不用动,复用性和扩展性都拉满。

Spring 源码中的应用

模板方法模式在 Spring 框架中应用广泛,尤其在 Spring JDBC 的 JdbcTemplate 中体现得淋漓尽致。JdbcTemplate 封装了 JDBC 操作的通用流程(如获取连接、执行 SQL、处理结果集、关闭资源),具体查询或更新逻辑由开发者通过回调接口实现。

源码分析 :以下是 JdbcTemplateexecute 方法(引用 Spring Framework 5.3.33,路径:org.springframework.jdbc.core.JdbcTemplate),展示模板方法模式的实现:

java 复制代码
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
    public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action) throws DataAccessException {
        Assert.notNull(psc, "PreparedStatementCreator must not be null");
        Assert.notNull(action, "PreparedStatementCallback must not be null");

        Connection con = DataSourceUtils.getConnection(obtainDataSource());
        PreparedStatement ps = null;
        try {
            ps = psc.createPreparedStatement(con);
            ResultSet rs = null;
            if (action != null) {
                T result = action.doInPreparedStatement(ps); // 子类实现的回调
                handleWarnings(ps);
                return result;
            }
            return null;
        }
        catch (SQLException ex) {
            throw translateSQLException("JdbcTemplate", ex);
        }
        finally {
            JdbcUtils.closeStatement(ps);
            DataSourceUtils.releaseConnection(con, getDataSource());
        }
    }
}

模板方法体现

  • 模板方法execute 方法定义了 JDBC 操作的固定流程(获取连接 → 创建语句 → 执行回调 → 处理异常 → 释放资源)。
  • 抽象步骤PreparedStatementCallback 接口的 doInPreparedStatement 方法由开发者实现,定制具体 SQL 执行逻辑。
  • 固定流程 :连接管理和资源释放由 JdbcTemplate 保证,子类无需关心。

解决问题JdbcTemplate 通过模板方法模式,统一了 JDBC 操作的繁琐流程,开发者只需关注业务逻辑(如 SQL 和结果处理),大大降低开发复杂度和错误率,同时保证资源管理的一致性。

Java 代码案例

以下基于 Spring Boot 实现一个报表生成系统,展示模板方法模式在企业级开发中的应用。报表生成流程包括"加载数据 → 格式化 → 导出文件",支持 PDF 和 Excel 两种格式。

代码实现

java 复制代码
// 抽象报表生成器
public abstract class ReportGenerator {

    // 模板方法,定义生成报表的固定流程
    public final void generateReport() {
        List<?> data = loadData();
        String formattedContent = formatData(data);
        exportFile(formattedContent);
    }

    // 固定步骤:加载数据
    protected List<?> loadData() {
        // 模拟从数据库加载数据
        return Arrays.asList("Data1", "Data2", "Data3");
    }

    // 抽象步骤:子类实现数据格式化
    protected abstract String formatData(List<?> data);

    // 抽象步骤:子类实现文件导出
    protected abstract void exportFile(String content);
}

// PDF 报表生成器
@Component
public class PdfReportGenerator extends ReportGenerator {

    @Override
    protected String formatData(List<?> data) {
        // 模拟 PDF 格式化
        return "PDF Report:\n" + data.stream().collect(Collectors.joining("\n"));
    }

    @Override
    protected void exportFile(String content) {
        // 模拟导出 PDF 文件
        System.out.println("Exporting PDF:\n" + content);
    }
}

// Excel 报表生成器
@Component
public class ExcelReportGenerator extends ReportGenerator {

    @Override
    protected String formatData(List<?> data) {
        // 模拟 Excel 格式化
        return "Excel Report:\n" + data.stream().collect(Collectors.joining(","));
    }

    @Override
    protected void exportFile(String content) {
        // 模拟导出 Excel 文件
        System.out.println("Exporting Excel:\n" + content);
    }
}

// 报表服务
@Service
public class ReportService {

    @Autowired
    private List<ReportGenerator> generators;

    public void generateAllReports() {
        generators.forEach(ReportGenerator::generateReport);
    }
}

代码说明

  • 模板方法体现ReportGeneratorgenerateReport 方法定义了报表生成的固定流程(加载 → 格式化 → 导出)。final 关键字确保流程不可更改。
  • 抽象步骤formatDataexportFile 由子类 PdfReportGeneratorExcelReportGenerator 实现,定制具体格式和导出逻辑。
  • 解决的问题:统一报表生成流程,减少重复代码。新增报表类型(如 CSV)只需实现新子类,符合开闭原则。
  • 好处:代码复用性高,流程逻辑集中,维护成本低。Spring 的依赖注入让扩展和管理生成器更灵活。
  • 运行方式 :通过 ReportService 调用 generateAllReports,自动执行所有报表生成器,输出 PDF 和 Excel 格式的报表。

总结

模板方法模式就像一个经验丰富的厨师,给你一份万能菜谱,关键步骤让你自由发挥。它通过固定流程减少重复代码,通过抽象步骤保证灵活性。在 Spring 的 JdbcTemplate 中,模板方法模式让 JDBC 操作变得简单而可靠,开发者只需写 SQL 和结果处理,框架搞定连接和资源管理。我们的报表案例进一步展现了它的实用性:统一的生成流程让代码清晰,新增报表类型毫不费力。

(对您有帮助 && 觉得我总结的还行) -> 受累点个免费的赞👍,谢谢

相关推荐
netyeaxi8 小时前
Java:使用spring-boot + mybatis如何打印SQL日志?
java·spring·mybatis
收破烂的小熊猫~8 小时前
《Java修仙传:从凡胎到码帝》第四章:设计模式破万法
java·开发语言·设计模式
小七mod8 小时前
【MyBatis】MyBatis与Spring和Spring Boot整合原理
spring boot·spring·mybatis
程序猿小D11 小时前
[附源码+数据库+毕业论文]基于Spring+MyBatis+MySQL+Maven+jsp实现的个人财务管理系统,推荐!
java·数据库·mysql·spring·毕业论文·ssm框架·个人财务管理系统
佛祖让我来巡山11 小时前
【工厂和策略设计模式妙用】解决接口选择与多重if-else 问题
设计模式·策略模式·工厂模式
永日4567012 小时前
学习日记-spring-day42-7.7
java·学习·spring
二十雨辰13 小时前
[尚庭公寓]07-Knife快速入门
java·开发语言·spring
NE_STOP15 小时前
SpringBoot--简单入门
java·spring
hqxstudying15 小时前
Java创建型模式---原型模式
java·开发语言·设计模式·代码规范
张小洛17 小时前
Spring AOP 设计解密:代理对象生成、拦截器链调度与注解适配全流程源码解析
java·后端·spring·spring aop·aop