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()做了切片,从代码中剥离出来,使代码复用性更高,也更简洁