使用继承或接口实现模板方法的方式与函数回调的感悟
2017-06-02 10:56
866 查看
关于模板方法和函数回调的感悟
模板方法是将将一些方法公公共的操作提取出来的一种很好的方法,利用继承或接口的特性,再结合模板方法的的特性,我们在减少重复代码次数的情况下实现一批相关的方法。 下面通过两个例子,我们来感受和学习一下这种设计模式。
1.使用类继承实现
一般步骤: 1. 先写出解决该类事情其中 的一件的解决方案。 2. 分析代码,把会发生变化的代码抽取出来独立成一个方法。把该方法描述成一个抽象的方法。 3. 使用final修饰模板方法,防止别人 重写你的模板方法。
下面通过一个简单的小例子来说明一下,在这个需求中我们希望有一种方法能够计算其他任意方法的执行时间。 测试代码如下:
abstract class MyRuntime{ //实现计算某种方法代码执行的时间 public final void getTime(){ long startTime = System.currentTimeMillis(); //记录开始的时间 code(); long endTime = System.currentTimeMillis(); //记录结束的时间. System.out.println("运行时间 :"+ (endTime-startTime)); } //需要计算执行时间的代码,由子类继承实现 public abstract void code(); } class Demo11 extends MyRuntime { public static void main(String[] args) { Demo11 d = new Demo11(); d.getTime(); } //code方法内部就写要计算运行时间的代码; public void code(){ int i = 0; while(i<100){ System.out.println("i="+i); i++; } } }
2. 使用接口实现
通过接口来实现模板方法时经常会与函数回调结合着使用,这里我们一以Spring中HibernateTemplate类实现的方法为例。 在HibernateTemplate中由于需要与数据库交互,所以每一个对数据库进行操作的方法都需要在执行之前获取绑定当前线程的Session,而在方法具体操作执行之后释放Session资源。基于这一原因,在HibernateTemplate类中就引用了模板模式和函数回调的思想。 下面,我们来看一下具体的代码。
public Serializable save(final Object entity) throws DataAccessException { //方法执行的的第一步时调用executeWithNativeSession方法,并提供HibernateCallback接口中回调函数的实现 //executeWithNativeSession方法接收接口HibernateCallback,返回另一个函数doExecute return executeWithNativeSession(new HibernateCallback<Serializable>() { //HibernateCallback中抽象函数的实现,用来执行save方法特有的功能 @Override public Serializable doInHibernate(Session session) throws HibernateException { checkWriteOperationAllowed(session); return session.save(entity); } }); } 简单说明:HibernateCallback 是一个接口,接口中有一个Abstract方法doInHibernate(Session session) 下面我们来看一下executeWithNativeSession方法的源代码: public <T> T executeWithNativeSession(HibernateCallback<T> action) { return doExecute(action, true); } 可以发现executeWithNativeSession函数只是转而去执行doExecute(action, true)函数,我们在去看一下这个函数的代码: protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNativeSession) throws DataAccessException { Assert.notNull(action, "Callback object must not be null"); Session session = null; boolean isNew = false; try { //通过我们向Spring注入的SessionFactory工厂类,获取与当前线程绑定的Session,这是是为了实现事务功能 session = getSessionFactory().getCurrentSession(); } catch (HibernateException ex) { logger.debug("Could not retrieve pre-bound Hibernate session", ex); } if (session == null) { session = getSessionFactory().openSession(); session.setFlushMode(FlushMode.MANUAL); isNew = true; } try { enableFilters(session); Session sessionToExpose = (enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session)); //执行回调函数,去执行函数特有方法即session.save(entity); return action.doInHibernate(sessionToExpose); } catch (HibernateException ex) { throw SessionFactoryUtils.convertHibernateAccessException(ex); } catch (RuntimeException ex) { // Callback code threw application exception... throw ex; } //释放相关资源 finally { if (isNew) { SessionFactoryUtils.closeSession(session); } else { disableFilters(session); } } } 这样一来,HibernateTemplate类中的操作数据库的方法就都会执行 doExecute()方法,在该方法中获取Session以及释放资源,处理共有的操作,而且由于提供的HibernateCallback的实现类不同,在函数回调时就会执行自己特有的代码。
总结:其实上面所说回调,简单的可以说是,将自己的引用(接口实现类)作为参数传给别的方法,在别的方法里面,通过自己的引用(接口实现类)调用自己实现的方法。
相关文章推荐
- Go语言使用组合的方式实现多继承的方法
- 记录 “Thinkphp 3.2及以上版本实现支付宝担保交易、即时到账接口类、函数和使用方法”
- js接口的方式实现模板方法
- Fragment学习之使用接口回调的方式实现Fragment与Activity通信
- 使用接口实现多继承的方法
- 启动线程的五种方式方法(通过继承Thread类或实现Runnable接口)
- spring RowMapper回调接口的使用 以及jdbc模板提供的queryfor系列的方法摘要
- 模板方法和接口参数的联合使用 [ 同一请求,不同处理方式 ]
- 30. 代码实例-设计模式-回调方式使用模板方法
- C#中使用托管C++类,委托调用,以供托管C++类的成员函数回调的实现方式
- Case:接口实现类的方法上使用AspectJ方式实现aop的异常问题
- 线程 创建和启动线程的两种方式 实现Runnable接口 继承Thread类 重写唯一方法run()
- Java中使用接口实现多继承和多态的方法
- c++实现回调函数及使用方法
- Fragment学习之使用接口回调的方式实现Fragment与Activity通信
- 继承有几种方式,分别是什么,想要实现继承可以使用哪些方法
- C++使用模板、函数指针、接口和lambda表达式这四种方法做回调函数的区别比较
- 使用接口实现函数的回调
- JAVA多线程实现的三种方式(继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程)
- JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没