Spring对JDBC的抽象和对Hibernate的集成,都采用了一种理念或者处理方式,那就是Template模式与相应的Callback
接口相结合。比如JdbcTemplate的execute方法、HibernateTemplate的execute方法。
以JdbcTempalte为例,如下:
public abstract class JdbcTemplate {
public final Object execute(String sql){
Connectioncon=null;
Statementstmt=null;
try
{
con=getConnection();
stmt=con.createStatement();
ObjectretValue=executeWithStatement(stmt,sql);
returnretValue;
}
catch(SQLExceptione){
...
}
finally
{
closeStatement(stmt);
releaseConnection(con);
}
}
protected abstract ObjectexecuteWithStatement(Statement stmt,String sql);
}
这样处理之后,JDBC代码的使用得到了规范,连接释放等问题也得到了统一的管理。
Templatemethod被广泛的使用,像Servlet就是使用这个模式。Template mothod模式虽然能简化很多重复的代码,但这种模式的也有不少限制。
Templatemothod将一个功能的实现分成许多小的步骤,在父类中定义了这些步骤的顺序,让子类来具体实现每一个小的步骤。这些小
的步骤是protected,以防止用户不正确的使用这些小的步骤而产生异常。这样就产生了一个限制,那就是你需要继承Template,然后
在子类中重新实现具体的小步骤。
如果这个Template有许多方法,就像JdbcTemplate,如果你每次继承这个庞大的类,然后只是重写某个小步骤中来订制你自己的功能,
就会显得非常笨重,更何况数据库操作使用的如此频繁,难道你每进行一个操作就通过继承订制一个,显然不可能这么做。
public interface StatementCallback{
Object doWithStatement(Statementstmt);
}
public class JdbcTemplate {
public final Object execute(StatementCallbackcallback){
Connectioncon=null;
Statementstmt=null;
try
{
con=getConnection();
stmt=con.createStatement();
ObjectretValue=callback.doWithStatement(stmt);
returnretValue;
}
catch(SQLExceptione){
...
}
finally
{
closeStatement(stmt);
releaseConnection(con);
}
}
...//其它方法定义
}
使用如下:
JdbcTemplatejdbcTemplate=...;
final String sql=...;
StatementCallback callback=new StatementCallback(){
publicObject=doWithStatement(Statement stmt){
return ...;
}
}
jdbcTemplate.execute(callback);
CallBack避免了用户继承Template,而是直接让用户实现去CallBack接口,达到了去掉重复代码的效果;只需要实现某些CallBack就可轻松订制出Template,增加了很大的灵活性。
从UML关系分析
Template模式使用继承,结合Callback之后,只是简单的依赖,耦合性变弱,不用必须从父类继承多余的东西。
从对象的粒度分析
一般情况下如果一个操作的子步骤比较少(三个以下),比如用户只需要定制一个方法能就达到用户的要求,或者你不想生
成太细粒度的对象时,用Callback来代替templatemethod能够获得更好的灵活性。
而如果子步骤多,需要我们真正去具体实现,则使用templatemethod。因为你可能需要传递多个Callback作为参数,并让
用户去实现,这相当于你把每个小步骤封装成为接口,然后分别实现,这时便会产生大量的类和接口,显然没有达到方便灵
活的效果。