一.模式简介
下面是模板方法模式的结构图。直接把《设计模式》上的图拿过来用下:
|
2) ConcreteClass(具体类):实现父类中的抽象方法以完成算法中与特定子类相关的步骤。
下面我们来实现下AbstractClass,因为还是有一些实现细节需要我们注意:
public abstract class AbstractClass {
/*
* this template method should be declare as final
*/
final void templateMethod(){
primitiveOperation1();
primitiveOperation2();
concreteOperation();
hook();
}
/*
* a hook method, it's up to subclass to overrite it.
*/
private void hook() {}
final void concreteOperation() {
// TODO Auto-generated method stub
}
abstract void primitiveOperation2();
abstract void primitiveOperation1();
}
注意:
1.模版方法应该被声明为final的,也就是说避免子类的覆盖,导致算法顺序的改变。
2.primitiveOperation1.2声明为了抽象类,有子类方法覆盖。
3.hook()方法有空的或者默认的实现。hook的存在,可以让子类有能力对算法的不同点进行挂钩。要不要hook,由子类来决定。
二.模式的应用
public static void sort(Object[] a) {
Object[] aux = (Object[])a.clone();
mergeSort(aux, a, 0, a.length, 0);
}
private static void mergeSort(Object[] src,
Object[] dest,
int low,
int high,
int off) {
int length = high - low;
// Insertion sort on smallest arrays
for (int i=low; i<high; i++)
for (int j=i; j>low &&
((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
swap(dest, j, j-1);
return;
// other condition implment
}
Arrays.sort方法只是一个辅助方法,用来做成对象的拷贝,真正的排序工作在mergeSort中完成,而mergeSort方法的冒泡排序操作依赖于compareTo()方法的实现来完成。
现在我们看看Spring是如何做Template的,打开spring源代码发现在HibernateTemplate中包含execute(HibernateCallback action);该方法扮演的角色就是类似与上图中的AbstractClass类中的TemplateMothod.而该方法有只有一个唯一参数就是接口HibernateCallback所引用的对象action,在改接口抽象出了变化的数据库操作。
public interface HibernateCallback {
Object doInHibernate(Session session) throws HibernateException, SQLException;
}
就像我们在前面形容的一样HibernateCallback扮演一个“钩子(hook)“的角色,这样用接口和不同的接口实现类替代了Template Method模式中的继承关系同时也将模板方法execute(HibernateCallback action)独立出来。
看看execute的实现:
public Object execute(HibernateCallback action, boolean exposeNativeSession) throws DataAccessException {
Session session = getSession();
boolean existingTransaction = SessionFactoryUtils.isSessionTransactional(session, getSessionFactory());
if (existingTransaction) {
logger.debug("Found thread-bound Session for HibernateTemplate");
}
FlushMode previousFlushMode = null;
try {
previousFlushMode = applyFlushMode(session, existingTransaction);
Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));
Object result = action.doInHibernate(sessionToExpose);
flushIfNecessary(session, existingTransaction);
return result;
}
catch (HibernateException ex) {
throw convertHibernateAccessException(ex);
}
catch (SQLException ex) {
throw convertJdbcAccessException(ex);
}
catch (RuntimeException ex) {
// Callback code threw application exception...
throw ex;
}
finally {
if (existingTransaction) {
logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
if (previousFlushMode != null) {
session.setFlushMode(previousFlushMode);
}
}
else {
SessionFactoryUtils.releaseSession(session, getSessionFactory());
}
}
}
我们可以看到,在excute方法中做了对Session的管理和事务的控制,而代码:
Object result = action.doInHibernate(sessionToExpose);
则执行实际的数据库操作。
我们看看HibernateTemplate对hibernate的一个get方法的封装:
public Object get(final Class entityClass, final Serializable id, final LockMode lockMode)
throws DataAccessException {
return execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
if (lockMode != null) {
return session.get(entityClass, id, lockMode);
}
else {
return session.get(entityClass, id);
}
}
}, true);
}
在该段代码中用匿名类声明了一个接口实现,并将改对象作为参数传给
excute
方法。如此,便实现了
Template Method
设计模式。