模板方法模式实战

发布时间:2026/5/20 1:11:21

模板方法模式实战 模板方法模式实战引言模板方法模式是行为型设计模式的一种它定义了一个算法的骨架将某些步骤延迟到子类中实现。Spring的JdbcTemplate、RestTemplate等都是模板方法模式的经典应用。本文将详细介绍模板方法模式的实现方式以及在Java/Spring中的应用场景。一、模式结构1.1 基本结构public abstract class DataProcessor { // 模板方法 public final void process() { connect(); validate(); processData(); save(); disconnect(); } protected void connect() { System.out.println(Connecting to data source...); } protected abstract void validate(); protected abstract void processData(); protected abstract void save(); protected void disconnect() { System.out.println(Disconnecting...); } } public class FileProcessor extends DataProcessor { Override protected void validate() { System.out.println(Validating file format...); } Override protected void processData() { System.out.println(Processing file data...); } Override protected void save() { System.out.println(Saving to database...); } }二、JdbcTemplate模板方法2.1 核心结构public abstract class JdbcAccessor { protected DataSource dataSource; public void setDataSource(DataSource dataSource) { this.dataSource dataSource; } } public class JdbcTemplate extends JdbcAccessor { public T T execute(ConnectionCallbackT action) { Connection conn null; try { conn DataSourceUtils.getConnection(dataSource); return action.doInConnection(conn); } finally { DataSourceUtils.releaseConnection(conn, dataSource); } } public T T query(String sql, RowMapperT rowMapper) { return execute(conn - { Statement stmt null; ResultSet rs null; try { stmt conn.createStatement(); rs stmt.executeQuery(sql); ListT results new ArrayList(); while (rs.next()) { results.add(rowMapper.mapRow(rs, rs.getRow())); } return results.isEmpty() ? null : results.get(0); } finally { closeResultSet(rs); closeStatement(stmt); } }); } private void closeResultSet(ResultSet rs) { // 关闭资源 } private void closeStatement(Statement stmt) { // 关闭语句 } }2.2 自定义JdbcTemplatepublic class EnhancedJdbcTemplate extends JdbcTemplate { public T T executeWithRetry(String sql, RowMapperT rowMapper, int maxRetries) { int attempts 0; while (attempts maxRetries) { try { return query(sql, rowMapper); } catch (DataAccessException e) { attempts; if (attempts maxRetries) { throw e; } try { Thread.sleep(1000 * attempts); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); throw new DataAccessException(Retry interrupted) {}; } } } return null; } }三、RestTemplate模板3.1 请求执行器public class RestTemplate { private final ListHttpMessageConverter? messageConverters new ArrayList(); private final ClientHttpRequestFactory requestFactory; public T ResponseEntityT exchange(String url, HttpMethod method, HttpEntity? requestEntity, ClassT responseType, Object... uriVariables) { // 1. 创建请求 ClientHttpRequest request createRequest( url, method, uriVariables); // 2. 填充headers和body if (requestEntity ! null) { writeHeaders(request, requestEntity.getHeaders()); writeBody(request, requestEntity.getBody()); } // 3. 执行请求 ClientHttpResponse response executeRequest(request); // 4. 处理响应 return handleResponse(response, responseType); } protected ClientHttpRequest createRequest(String url, HttpMethod method, Object... uriVariables) { URI uri UriComponentsBuilder .fromUriString(url) .buildAndExpand(uriVariables) .toUri(); return requestFactory.createRequest(uri, method); } protected ClientHttpResponse executeRequest( ClientHttpRequest request) { try { return request.execute(); } catch (IOException e) { throw new ResourceAccessException( I/O error on request.getMethod() request, e); } } protected T ResponseEntityT handleResponse( ClientHttpResponse response, ClassT responseType) { // 处理响应 return null; } }四、流程处理模板4.1 业务流程模板public abstract class OrderProcessTemplate { public final Order process(Order order) { validate(order); reserveStock(order); calculateAmount(order); processPayment(order); confirmOrder(order); sendNotification(order); return order; } protected void validate(Order order) { if (order.getItems().isEmpty()) { throw new IllegalArgumentException(Order is empty); } } protected abstract void reserveStock(Order order); protected abstract void calculateAmount(Order order); protected abstract void processPayment(Order order); protected void confirmOrder(Order order) { order.setStatus(OrderStatus.CONFIRMED); order.setConfirmTime(LocalDateTime.now()); } protected void sendNotification(Order order) { System.out.println(Sending notification for order: order.getId()); } } Service public class OnlineOrderProcessor extends OrderProcessTemplate { Override protected void reserveStock(Order order) { System.out.println(Reserving stock online...); } Override protected void calculateAmount(Order order) { BigDecimal total order.getItems().stream() .map(OrderItem::getAmount) .reduce(BigDecimal.ZERO, BigDecimal::add); order.setTotalAmount(total); } Override protected void processPayment(Order order) { System.out.println(Processing online payment...); } }4.2 数据导入模板public abstract class DataImportTemplate { public final ImportResult importData(String filePath) { InputStream inputStream null; try { inputStream openFile(filePath); ListRecord records readRecords(inputStream); validateRecords(records); ListRecord validRecords filterValidRecords(records); return saveRecords(validRecords); } catch (Exception e) { return ImportResult.failure(e.getMessage()); } finally { closeFile(inputStream); } } protected InputStream openFile(String filePath) { try { return new FileInputStream(filePath); } catch (FileNotFoundException e) { throw new ImportException(File not found: filePath); } } protected abstract ListRecord readRecords(InputStream input); protected void validateRecords(ListRecord records) { for (Record record : records) { if (!isValid(record)) { throw new ValidationException( Invalid record: record); } } } protected abstract boolean isValid(Record record); protected ListRecord filterValidRecords(ListRecord records) { return records.stream() .filter(this::isValid) .collect(Collectors.toList()); } protected abstract ImportResult saveRecords(ListRecord records); protected void closeFile(InputStream inputStream) { if (inputStream ! null) { try { inputStream.close(); } catch (IOException ignored) {} } } }五、Callback回调5.1 Spring的Callback接口FunctionalInterface public interface JdbcCallbackT { T doInJdbc(Connection connection) throws SQLException; } public T T execute(JdbcCallbackT callback) { Connection conn getConnection(); try { return callback.doInJdbc(conn); } finally { releaseConnection(conn); } } // 使用 jdbcTemplate.execute(conn - { try (PreparedStatement ps conn.prepareStatement( SELECT * FROM users WHERE id ?)) { ps.setLong(1, userId); try (ResultSet rs ps.executeQuery()) { if (rs.next()) { return mapToUser(rs); } } } return null; });5.2 自定义CallbackFunctionalInterface public interface DataProcessCallbackT, R { R process(T data) throws Exception; } public class DataProcessTemplate { public T, R R execute(T input, DataProcessCallbackT, R callback) { try { return callback.process(input); } catch (Exception e) { throw new ProcessException(Processing failed, e); } } } Service public class OrderService { private final DataProcessTemplate template; public Order confirmOrder(Order order) { return template.execute(order, o - { validateOrder(o); calculateTotal(o); return saveOrder(o); }); } }六、策略与模板方法结合6.1 策略作为模板参数public abstract class DataExportTemplate { public final void export(List? data, ExportStrategy strategy) { prepareExport(); String content strategy.format(data); validateContent(content); writeToFile(content); completeExport(); } protected void prepareExport() { System.out.println(Preparing export...); } protected abstract void validateContent(String content); protected void writeToFile(String content) { System.out.println(Writing to file: content); } protected void completeExport() { System.out.println(Export completed); } } FunctionalInterface public interface ExportStrategy { String format(List? data); } public class CsvExportStrategy implements ExportStrategy { Override public String format(List? data) { return data.stream() .map(Object::toString) .collect(Collectors.joining(,)); } }七、Spring Batch模式7.1 ItemReaderpublic interface ItemReaderT { T read(); } public abstract class AbstractItemReaderT implements ItemReaderT { Override public final T read() { T item doRead(); if (item ! null) { log(Read item: item); } return item; } protected abstract T doRead(); protected void log(String message) { System.out.println([Reader] message); } }7.2 ItemProcessorFunctionalInterface public interface ItemProcessorI, O { O process(I item) throws Exception; } public class ValidationProcessorI implements ItemProcessorI, I { private final ListItemValidatorI validators; Override public I process(I item) throws Exception { for (ItemValidatorI validator : validators) { validator.validate(item); } return item; } }八、最佳实践8.1 使用final修饰模板方法public abstract class BaseTemplate { public final void execute() { // 防止被子类重写 step1(); step2(); step3(); } protected abstract void step1(); protected abstract void step2(); protected abstract void step3(); }8.2 钩子方法public abstract class HookTemplate { public final void process() { beforeProcess(); doProcess(); afterProcess(); } protected void beforeProcess() { // 空实现钩子 } protected abstract void doProcess(); protected void afterProcess() { // 默认实现钩子 System.out.println(Cleanup...); } }总结模板方法模式通过将不变的部分封装在父类变化的部分延迟到子类实现达到了代码复用的目的。Spring的JdbcTemplate、RestTemplate等是这一模式的经典应用。在实际开发中可以结合Callback接口和Lambda表达式使模板方法模式更加灵活和简洁。

相关新闻