模板方法模式
引言
模板方法模式是一种行为型设计模式,定义了一个操作的骨架,将具体步骤延迟到子类实现。它的核心是通过抽象类或接口固定算法的总体流程,同时允许子类在不改变结构的情况下定制部分步骤。就像烹饪一道菜:模板方法给出"炒菜"的通用步骤(热锅、放油、翻炒),具体食材和调料由子类决定。在企业开发中,模板方法模式常用于流程化操作,如数据处理、事务管理、请求处理等场景,兼顾代码复用和灵活性。它的魅力在于既保证了流程的稳定性,又给子类留足发挥空间。
实际开发中的用途
模板方法模式适合需要统一流程但部分步骤可定制的场景。比如,批量数据导入系统:无论导入用户数据还是订单数据,流程都是"读取文件 → 校验数据 → 持久化",但具体校验和持久化逻辑因数据类型不同。模板方法模式通过抽象类定义通用流程,子类实现差异化步骤,避免重复代码。
举个例子:开发一个报表生成系统,报表有多种类型(如PDF、Excel),但生成流程一致:加载数据 → 格式化 → 导出文件。用模板方法模式,抽象类定义流程,子类实现格式化和导出的具体逻辑。如果要加个新报表类型(比如CSV),只写个新子类,流程代码不用动,复用性和扩展性都拉满。
Spring 源码中的应用
模板方法模式在 Spring 框架中应用广泛,尤其在 Spring JDBC 的 JdbcTemplate
中体现得淋漓尽致。JdbcTemplate
封装了 JDBC 操作的通用流程(如获取连接、执行 SQL、处理结果集、关闭资源),具体查询或更新逻辑由开发者通过回调接口实现。
源码分析 :以下是 JdbcTemplate
的 execute
方法(引用 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);
}
}
代码说明
- 模板方法体现 :
ReportGenerator
的generateReport
方法定义了报表生成的固定流程(加载 → 格式化 → 导出)。final
关键字确保流程不可更改。 - 抽象步骤 :
formatData
和exportFile
由子类PdfReportGenerator
和ExcelReportGenerator
实现,定制具体格式和导出逻辑。 - 解决的问题:统一报表生成流程,减少重复代码。新增报表类型(如 CSV)只需实现新子类,符合开闭原则。
- 好处:代码复用性高,流程逻辑集中,维护成本低。Spring 的依赖注入让扩展和管理生成器更灵活。
- 运行方式 :通过
ReportService
调用generateAllReports
,自动执行所有报表生成器,输出 PDF 和 Excel 格式的报表。
总结
模板方法模式就像一个经验丰富的厨师,给你一份万能菜谱,关键步骤让你自由发挥。它通过固定流程减少重复代码,通过抽象步骤保证灵活性。在 Spring 的 JdbcTemplate
中,模板方法模式让 JDBC 操作变得简单而可靠,开发者只需写 SQL 和结果处理,框架搞定连接和资源管理。我们的报表案例进一步展现了它的实用性:统一的生成流程让代码清晰,新增报表类型毫不费力。
(对您有帮助 && 觉得我总结的还行) -> 受累点个免费的赞👍,谢谢