图文无关
1. 什么是 Template Method 模式?
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 Template Method 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
Template Method 适用于下列情况:
图1-1:TemplateMehod UML图
TemplateMethod代码示例:
package webj2ee.tmplateMethod;
public abstract class AbstractClass {
// 基本操作
protected abstract void primitiveOperation1();
// 基本操作
protected abstract void primitiveOperation2();
// 模板方法
public void templateMethod(){
primitiveOperation1();
primitiveOperation2();
}
}
package webj2ee.tmplateMethod;
public class ConcreteClass extends AbstractClass{
@Override
protected void primitiveOperation1() {
// 业务逻辑处理
}
@Override
protected void primitiveOperation2() {
// 业务逻辑处理
}
}
package webj2ee.tmplateMethod;
public class Client {
public static void main(String[] args) {
AbstractClass clz = new ConcreteClass();
// 调用模板方法
clz.templateMethod();
}
}
2. 在 Spring 中的应用?
Template Method(模板方法)模式在Spring中应用广泛,如:jdbcTemplate、 hibernateTemplate、JndiTemplate 等都无疑使用了模板模式,并配合 Callback 一起使用,极其灵活。
没啥好说的了,看源码体会吧
@Override
@Nullable
public <T> T execute(StatementCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(obtainDataSource());
Statement stmt = null;
try {
stmt = con.createStatement();
applyStatementSettings(stmt);
T result = action.doInStatement(stmt);
handleWarnings(stmt);
return result;
}
catch (SQLException ex) {
// Release Connection early, to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
String sql = getSql(action);
JdbcUtils.closeStatement(stmt);
stmt = null;
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw translateException("StatementCallback", sql, ex);
}
finally {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
@Override
@Nullable
public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {
Assert.notNull(sql, "SQL must not be null");
Assert.notNull(rse, "ResultSetExtractor must not be null");
if (logger.isDebugEnabled()) {
logger.debug("Executing SQL query [" + sql + "]");
}
/**
* Callback to execute the query.
*/
class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
@Override
@Nullable
public T doInStatement(Statement stmt) throws SQLException {
ResultSet rs = null;
try {
rs = stmt.executeQuery(sql);
return rse.extractData(rs);
}
finally {
JdbcUtils.closeResultSet(rs);
}
}
@Override
public String getSql() {
return sql;
}
}
return execute(new QueryStatementCallback());
}