论坛首页 Java企业应用论坛

浅析java callback 回调模式

浏览 8601 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-08-03  
看过spring、hibernate源码的朋友对callback回调模式应该并不陌生,用一句话来概括就是:“if you call me, i will call back”,说白了,就是有相互依赖关系的两个类之间的互相调用,现在看看下面的代码模型:

package com.cuishen.callback;

public class Context implements A.Callback {

	private A a;
	
	public void begin() {
		System.out.println("begin ...");
	}

	public void end() {
		System.out.println("end ...");
	}
	
	public Context() {
		this.a = new A(this);
	}
	
	public void doSomething() {
		this.a.doIt();
	}
	
	public static void main(String args[]) {
		new Context().doSomething();
	}
}


package com.cuishen.callback;

public class A {
	
	private final Callback callback;
	
	public static interface Callback {
		public void begin();
		public void end();
	}
	public A(Callback callback) {
		this.callback = callback;
	}
	public void doIt() {
		callback.begin();
		System.out.println("do something ...");
		callback.end();
	}
}


上面的代码模型其原型是出自hibernate里的org.hibernate.jdbc.JDBCContext 和 org.hibernate.jdbc.ConnectionManager两个类,从上面的模型不难看出:Context类实现了A类的Callback接口,在Context类的构造器里将自己注入了A类,在Context类里调用A类的doIt()方法,这时就是:you call me;在doIt()方法体里调用了Context类的begin()和end()方法,这时就是:i call back。Context类 和 A类相互依赖,互相调用

在hibernate的源代码里大量使用了上面的callback回调模型,又如:org.hibernate.jdbc.JDBCContext 和 org.hibernate.impl.SessionImpl等等,可以自己去看源代码,这里不再赘述。

当然上面提到的模型中的两个类也可以写在同一个类里面,定义的Callback接口可以用内部匿名类来实现,比如下面的一个简单的dao实现:

package com.cuishen.callback;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class Dao {
	private interface Callback {
		Object doIt(Connection conn) throws SQLException;
	}
	private Object execute(Callback callback) throws SQLException {
		Connection conn = openConnection(); // 开启数据库连接
		try { return callback.doIt(conn); } // 执行具体操作并返回操作结果
		finally { closeConnection(conn); } // 关闭数据库连接
	}
	
	public Object sqlQuery(final String sql) throws SQLException {
		return execute(
			new Callback() {
				public Object doIt(Connection conn) throws SQLException {
					return conn.createStatement().executeQuery(sql);
				}
			}
		);
	}
	
	public Connection openConnection() throws SQLException {
		return DriverManager.getConnection("", null);
	}
	public void closeConnection(Connection conn) throws SQLException {
		if(conn != null && !conn.isClosed()) {
			conn.close();
		}
	}
}


用这种回调模式方便的把openConnection()和closeConnection()做了切片,从代码中剥离出来,使代码复用性更高,也更简洁

   发表时间:2009-08-03  
更准确的说是一种模板技巧,不要从callback字面理解,就像ioc,从字面上理解不出来的,而这种模板技巧是gof模式中的模板模式做不到的,最经典的就是spring的JDBCTemplate
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics