模板方法模式
基础概念
什么是模板方法模式?
答案: 模板方法模式(Template Method Pattern)定义一个操作中的算法骨架,将一些步骤延迟到子类中实现。
使用场景:
- 多个子类有公共方法
- 算法步骤固定,但某些步骤实现不同
- 需要控制子类扩展
优点:
- 封装不变部分,扩展可变部分
- 提取公共代码,便于维护
- 行为由父类控制,子类实现
缺点:
- 每个不同实现都需要子类
- 类数量增加
实现方式
基本实现?
答案:
java
// 抽象类
public abstract class AbstractClass {
// 模板方法
public final void templateMethod() {
step1();
step2();
step3();
}
// 具体方法
private void step1() {
System.out.println("步骤1:固定实现");
}
// 抽象方法,由子类实现
protected abstract void step2();
// 钩子方法,子类可选择性覆盖
protected void step3() {
System.out.println("步骤3:默认实现");
}
}
// 具体类A
public class ConcreteClassA extends AbstractClass {
@Override
protected void step2() {
System.out.println("步骤2:A的实现");
}
}
// 具体类B
public class ConcreteClassB extends AbstractClass {
@Override
protected void step2() {
System.out.println("步骤2:B的实现");
}
@Override
protected void step3() {
System.out.println("步骤3:B的自定义实现");
}
}实际应用
数据导入模板
答案:
java
// 抽象导入类
public abstract class DataImporter {
// 模板方法
public final void importData(String filePath) {
String data = readFile(filePath);
List<Object> records = parseData(data);
if (validateData(records)) {
saveData(records);
afterImport();
}
}
private String readFile(String filePath) {
System.out.println("读取文件: " + filePath);
return "file content";
}
protected abstract List<Object> parseData(String data);
protected abstract boolean validateData(List<Object> records);
private void saveData(List<Object> records) {
System.out.println("保存数据: " + records.size() + "条");
}
protected void afterImport() {
// 默认不做任何处理
}
}
// Excel导入
public class ExcelImporter extends DataImporter {
@Override
protected List<Object> parseData(String data) {
System.out.println("解析Excel数据");
return Arrays.asList("record1", "record2");
}
@Override
protected boolean validateData(List<Object> records) {
System.out.println("验证Excel数据");
return true;
}
}Spring中的模板方法
JdbcTemplate?
答案:
java
// JdbcTemplate的execute方法
public <T> T execute(StatementCallback<T> action) {
Connection con = DataSourceUtils.getConnection(getDataSource());
Statement stmt = null;
try {
stmt = con.createStatement();
T result = action.doInStatement(stmt);
return result;
} finally {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, getDataSource());
}
}练习题
- 模板方法模式和策略模式的区别?
- 什么时候使用钩子方法?
- 模板方法为什么要用final修饰?
- 如何避免模板方法过于复杂?
- 模板方法模式的应用场景有哪些?