Spring中常用的设计模式:模板模式

文章目录

定义

在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

实例分析

Spring中 Callback 模式和 Template 模式合用随处可见。
不论是与 Mybatis,还是与 Hibernate 的结合中,Spring 都使用到了 Template 模式与 Callback 技术,来达到简化代码实现的目的。Template 模式也即模板模式,用于对一些不太变化的流程进行模板化,与 Callback 结合,可以将变化的部分出离出来,使用 Callback 实现。然后根据不同的情况,向 Template 注入不同的 Callback。那些模板代码就没有必要重复写了。

下面以常用的 HibernateTemplate 为例进行简要简述。

由于 Java 的 JDBC 的开发过程中有许多步骤是固定的(建立连接,执行操作,释放连接),因此 Spring 采用模板方法对 JDBC 开发进行改进。模板方法定义过程的架构,一般是在一个抽象类中定义某个操作的一系列过程,将这一系列过程中的变化部分以抽象方法的形式给出,子类在进行这个操作时,只需要继承该抽象类,重写该抽象方法即可。代码如下:

public abstract class Ope{  
    public final void step1(){..}  
    public abstract  void step2();  
    public final void step3(){}  
    public final void execute(){  
        step1();  
        step2();  
        step3();  
    }  
}  
  
public class MyOpe extends Ope{  
   public void step2(){}  
   //public final void execute(){  
        //step1();  
        //step2();  
        //step3();  
   //}  
}  

这样,每一个具体的操作只需要实现 step2() 方法即可。

但是如果仅仅采用模板方法,就意味着每次进行增删改查操作,都需要继承某个类,在 Java 开发中通常会频繁操作数据库,这种方法会显得十分的不方便。

通常我们利用 HibernateTemplate 进行数据库操作时,是采用类似 ht.save(…) 的方式,在一个模板类中实现了所有的方法,而这其中用到了 Callback 模式。在 HibernateTemplate 模板类中有一个核心的方法,这个核心的方法完成相关的流程操作,其中的具体步骤通过回调传入的对象来完成(这个对象就是实现了Callback接口的类)。该类中的其它的方法(如 save,update 等)会通过Callback模式,调用这个核心的方法实现来完成最终的操作。这样就不需要实现多个类,只需在一个模板类中就可以完成全部的方法定义。
HibernateCallback 接口的代码如下:

 public interface HibernateCallback<T> {  
   T doInHibernate(Session session) throws HibernateException, SQLException;  
} 

它只有一个方法 doInHibernate 。HibernateTemplate 中的方法,如 save(),update() 的具体实现都采用匿名类的方式实现了该接口,在 doInHibernate 中完成具体的操作。以 save() 方法为例:

public Serializable save(final Object entity) throws DataAccessException {  
    return executeWithNativeSession(new HibernateCallback<Serializable>() {  
      public Serializable doInHibernate(Session session)   
        throws HibernateException {  
        checkWriteOperationAllowed(session);  
        return session.save(entity);  
            }  
        });  
    } 

save() 方法在 doInHibernate 方法中实现了 session.save(entity) 保存操作,而 executeWithNativeSession 方法可以看做是 HibernateTemplate 中的核心方法(它内部调用了 doExecute() 方法,doExecute() 方法才是真正的核心方法,它完成了一系列操作) :

       protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNewSession, boolean enforceNativeSession)  
                throws DataAccessException {  
      
            Assert.notNull(action, "Callback object must not be null");  
      
            Session session = (enforceNewSession ?  
                    SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession());  
            boolean existingTransaction = (!enforceNewSession &&  
                    (!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory())));  
            if (existingTransaction) {  
                logger.debug("Found thread-bound Session for HibernateTemplate");  
            }  
      
            FlushMode previousFlushMode = null;  
            try {  
                previousFlushMode = applyFlushMode(session, existingTransaction);  
                enableFilters(session);  
                Session sessionToExpose =  
                        (enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session));  
                T 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");  
                    disableFilters(session);  
                    if (previousFlushMode != null) {  
                        session.setFlushMode(previousFlushMode);  
                    }  
                }  
                else {  
                    // Never use deferred close for an explicitly new Session.  
                    if (isAlwaysUseNewSession()) {  
                        SessionFactoryUtils.closeSession(session);  
                    }  
                    else {  
                        SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());  
                    }  
                }  
            }  
        }  

Spring 中的 JdbcTemplate 等都采用了相同的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值