模板方法(Template Method)模式的定義:定義一個操作中的算法骨架驯用,而將算法的一些步驟延遲到子類中藕帜,使得子類可以不改變該算法結(jié)構(gòu)的情況下重定義該算法的某些特定步驟扛吞。它是一種類行為型模式.
其優(yōu)點有:
- 封裝了不變部分迷捧,擴展可變部分袜爪。
- 在父類中提取了公共的部分代碼,便于代碼復(fù)用垃它。
- 部分方法是由子類實現(xiàn)的,因此子類可以通過擴展方式增加相應(yīng)的功能,符合開閉原則国拇。
模式結(jié)構(gòu)
模板方法模式包含以下主要角色:
- 抽象類:負(fù)責(zé)給出一個算法的輪廓和骨架洛史。它由一個模板方法和若干個基本方法構(gòu)成。
- 具體子類:實現(xiàn)抽象類中所定義的抽象方法和鉤子方法酱吝,它們是一個頂級邏輯的一個組成步驟也殖。
源碼導(dǎo)讀
模板方法模式一般以“XXXtemplate”這種方式來命名,像我們所熟知的JdbcTemplate
就是采用模板方法模式設(shè)計的务热。
我們先看不使用JdbcTemplate
是怎么查詢的:
try{
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "1234");
String sql = "select nickname,comment,age from users";
statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
List<Users> usersList = new ArrayList<>();
while (resultSet.next()) {
Users users = new Users();
users.setNickname(resultSet.getString(1));
users.setComment(resultSet.getString(2));
users.setAge(resultSet.getInt(3));
usersList.add(users);
}
return usersList;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != statement) {
statement.close();
}
if (null != connection) {
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
return null;
我們執(zhí)行一次sql總是這樣一個流程:加載驅(qū)動-》獲取連接-》執(zhí)行sql-》創(chuàng)建一個Statement-》獲得返回值忆嗜。對于這種固定步驟的功能,我們就可以考慮用模板方法模式來實現(xiàn)了崎岂。
JDBCTemplate繼承了基類JdbcAccessor
和接口類JdbcOperation
捆毫。在基類JdbcAccessor
的設(shè)計中,對DataSource
數(shù)據(jù)源進行管理和配置冲甘。在JdbcOperation
接口中绩卤,定義了通過Jdbc操作數(shù)據(jù)庫的基本操作方法,而JdbcTemplate
提供這些接口方法的實現(xiàn)损合,比如execute方法省艳、query方法、update方法等嫁审。
在jdbcTemplate
的核心方法是execute
public <T> T execute(StatementCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(getDataSource());
Statement stmt = null;
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null &&
this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
stmt = conToUse.createStatement();
applyStatementSettings(stmt);
Statement stmtToUse = stmt;
if (this.nativeJdbcExtractor != null) {
stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);
}
T result = action.doInStatement(stmtToUse); // 回調(diào)
handleWarnings(stmt);
return result;
}
catch (SQLException ex) {
JdbcUtils.closeStatement(stmt);
stmt = null;
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);
}
finally {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
在模板方法模式中跋炕,類的方法被劃分為這幾類:模板方法(定義了算法的骨架,按某種順序調(diào)用其包含的基本方法)律适,基本方法(包括抽象方法辐烂,具體方法,鉤子方法)
這個execute
便是它的模板方法了捂贿。而getDataSource()
便是在父類中已經(jīng)實現(xiàn)的基本方法纠修。