在方法中定义算法的骨架,同时将一些步骤的实现推迟到子类。模板方法允许子类重新定义算法的某些步骤,而无需更改算法的结构。
真实世界理解:
人的一生都要经过幼年、少年、老年(具体方法),但每个人的一生又各不相同(抽象方法),虽然青年时期都要工作,但你可以选择对工作的态度(钩子方法)。
模板方法中三类角色:
创建一个人生算法骨架。
public static abstract class Life {
//具体方法
public final void life() {
//幼年
childhood();
//青年
youth();
//老年
old();
}
//抽象方法
public abstract void childhood();
private void youth() {
System.out.println(selectAttitude() + "地生活");
}
//抽象方法
public abstract void old();
//钩子方法
public String selectAttitude() {
return "";
}
}
程序员的一生
public static class Pogrammer extends Life {
@Override
public void childhood() {
System.out.println("调皮捣蛋");
}
@Override
public String selectAttitude() {
return "忙碌";
}
@Override
public void old() {
System.out.println("住进ICU");
}
}
老师的一生
public static class Teacher extends Life {
@Override
public void childhood() {
System.out.println("好好读书");
}
@Override
public String selectAttitude() {
return "辛勤";
}
@Override
public void old() {
System.out.println("钓鱼喝茶");
}
}
执行
public static void main(String[] args) {
//程序员的一生
Life pogrammer = new Pogrammer();
pogrammer.life();
//老师的一生
Life teacher = new Teacher();
teacher.life();
}
JdbcTemplate.update.StatementCallback.doInStatment和getSql就是一个抽象方法,留给子类扩展。
public int update(final String sql) throws DataAccessException {
Assert.notNull(sql, "SQL must not be null");
if (logger.isDebugEnabled()) {
logger.debug("Executing SQL update [" + sql + "]");
}
/**
* Callback to execute the update statement.
*/
class UpdateStatementCallback implements StatementCallback, SqlProvider {
@Override
public Integer doInStatement(Statement stmt) throws SQLException {
int rows = stmt.executeUpdate(sql);
if (logger.isTraceEnabled()) {
logger.trace("SQL update affected " + rows + " rows");
}
return rows;
}
@Override
public String getSql() {
return sql;
}
}
return updateCount(execute(new UpdateStatementCallback()));
}
execute就是具体方法/抽象方法,它定义了相同的步骤,包括打开链接、创建Statement、关闭连接,以此组成算法骨架。
public T execute(StatementCallback 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());
}
}
JDK 中 java.util.AbstractList抽象集合类,add作为抽象方法留给子类扩展,addAll作为具体方法为骨架。同时addAll也是抽象方法,也可以给子类扩展。
public abstract class AbstractList extends AbstractCollection implements List {
//新增元素的方法,留给子类实现
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
//模板方法。新增目标集合类的所有元素,默认调用 add 方法实现,也可以被子类重写
public boolean addAll(int index, Collection c) {
rangeCheckForAdd(index);
boolean modified = false;
for (E e : c) {
add(index++, e);
modified = true;
}
return modified;
}
}
菜鸟教程-模板方法
Github设计模式实现
大话设计模式
Github设计模式