java回调的两种应用

看过spring、hibernate源码的朋友对callback回调模式应该并不陌生,用一句话来概括就是:“if you call me, i will call back”,说白了,就是有相互依赖关系的两个类之间的互相调用,现在看看下面的代码模型: 

Java代码   收藏代码
  1. package com.cuishen.callback;  
  2.   
  3. public class Context implements A.Callback {  
  4.   
  5.     private A a;  
  6.       
  7.     public void begin() {  
  8.         System.out.println("begin ...");  
  9.     }  
  10.   
  11.     public void end() {  
  12.         System.out.println("end ...");  
  13.     }  
  14.       
  15.     public Context() {  
  16.         this.a = new A(this);  
  17.     }  
  18.       
  19.     public void doSomething() {  
  20.         this.a.doIt();  
  21.     }  
  22.       
  23.     public static void main(String args[]) {  
  24.         new Context().doSomething();  
  25.     }  
  26. }  
  27.   
  28.   
  29. package com.cuishen.callback;  
  30.   
  31. public class A {  
  32.       
  33.     private final Callback callback;  
  34.       
  35.     public static interface Callback {  
  36.         public void begin();  
  37.         public void end();  
  38.     }  
  39.     public A(Callback callback) {  
  40.         this.callback = callback;  
  41.     }  
  42.     public void doIt() {  
  43.         callback.begin();  
  44.         System.out.println("do something ...");  
  45.         callback.end();  
  46.     }  
  47. }  


上面的代码模型其原型是出自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实现: 

Java代码   收藏代码
  1. package com.cuishen.callback;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.DriverManager;  
  5. import java.sql.SQLException;  
  6.   
  7. public class Dao {  
  8.     private interface Callback {  
  9.         Object doIt(Connection conn) throws SQLException;  
  10.     }  
  11.     private Object execute(Callback callback) throws SQLException {  
  12.         Connection conn = openConnection(); // 开启数据库连接  
  13.         try { return callback.doIt(conn); } // 执行具体操作并返回操作结果  
  14.         finally { closeConnection(conn); } // 关闭数据库连接  
  15.     }  
  16.       
  17.     public Object sqlQuery(final String sql) throws SQLException {  
  18.         return execute(  
  19.             new Callback() {  
  20.                 public Object doIt(Connection conn) throws SQLException {  
  21.                     return conn.createStatement().executeQuery(sql);  
  22.                 }  
  23.             }  
  24.         );  
  25.     }  
  26.       
  27.     public Connection openConnection() throws SQLException {  
  28.         return DriverManager.getConnection(""null);  
  29.     }  
  30.     public void closeConnection(Connection conn) throws SQLException {  
  31.         if(conn != null && !conn.isClosed()) {  
  32.             conn.close();  
  33.         }  
  34.     }  
  35. }  


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



Java回调实现
 
有个这样的问题:老板(Boss)让工人(Worker)干完活告诉他干的情况如何。
 
实际上是一个典型的回调问题,Java实现如下:
 
/** 
* Created by IntelliJ IDEA. 
* User: leizhimin 
* Date: 2008-7-31 13:18:33 
* 事件接口 
*/
 
public  interface Event { 
     /** 
     * 返回发生事件信息 
     * 
     * @return 事件信息 
     */
 
     public String happendEvent(); 
}
 
/** 
* Created by IntelliJ IDEA. 
* User: leizhimin 
* Date: 2008-7-31 13:18:14 
* 事件A 
*/
 
public  class EventA  implements Event { 
     /** 
     * 返回发生事件信息 
     * 
     * @return 事件信息 
     */
 
     public String happendEvent() { 
         return  "发生了事件 EventA!"
    } 
}
 
/** 
* Created by IntelliJ IDEA. 
* User: leizhimin 
* Date: 2008-7-31 13:18:21 
* 事件B 
*/
 
public  class EventB  implements Event{ 
     /** 
     * 返回发生事件信息 
     * @return 事件信息 
     */
 
     public String happendEvent() { 
         return  "发生了事件 EventB!"
    } 
}
 
/** 
* Created by IntelliJ IDEA. 
* User: leizhimin 
* Date: 2008-7-31 13:20:48 
* 工人 
*/
 
public  class Worker { 
     private Event event;     //事件 
     private String name;     //工人姓名 
     private Boss boss;       //工人所属的老板 

     public Worker(String name, Boss boss) { 
         this.name = name; 
         this.boss = boss; 
    } 

     /** 
     * 干活 
     */
 
     public  void doWork() { 
        System.out.println(name +  " is doing working..."); 
         //工人挺辛苦,干着枯燥乏味的重复工作,哈哈 
         for ( int i = 0; i < 2000000; i++) { 
             int x = i / 234 + 234; 
        } 
        System.out.println(name +  " was finished work."); 
         //向老板说明发生的情况 
        boss.getWorkerEvent( this, event); 
    } 

     public Event getEvent() { 
         return event; 
    } 

     public  void setEvent(Event event) { 
         this.event = event; 
    } 

     public String getName() { 
         return name; 
    } 

     public  void setName(String name) { 
         this.name = name; 
    } 
}
 
/** 
* Created by IntelliJ IDEA. 
* User: leizhimin 
* Date: 2008-7-31 13:26:22 
* 老板 
*/
 
public  class Boss { 
     private String name; 

     public Boss(String name) { 
         this.name = name; 
    } 

     /** 
     * 老板接收工人的事件 
     * @param worker 工人 
     * @param event  事件 
     */
 
     public  void getWorkerEvent(Worker worker, Event event) { 
        System.out.println( "老板接收到事件信息: "+worker.getName() +  ": " + event.happendEvent()); 
    } 
}
 
/** 
* Created by IntelliJ IDEA. 
* User: leizhimin 
* Date: 2008-7-31 13:35:38 
* 测试类 
*/
 
public  class Test { 
     public  static  void main(String args[]){ 
         //初始化老板和工人 
        Boss boss =  new Boss( "老板"); 
        Worker worker1=  new Worker( "张三",boss); 
        Worker worker2=  new Worker( "李四",boss); 

         //捏造两个事件 
        Event event1 =  new EventA(); 
        Event event2 =  new EventB(); 

         //事件是工人发出的 
        worker1.setEvent(event1); 
        worker2.setEvent(event2); 

         //工人干活,干完了通知老板干的情况如何 
        worker1.doWork(); 
        worker2.doWork(); 

    } 
}
 
运行结果:
张三 is doing working... 
张三 was finished work. 
老板接收到事件信息: 张三: 发生了事件 EventA! 
李四 is doing working... 
李四 was finished work. 
老板接收到事件信息: 李四: 发生了事件 EventB! 

Process finished with exit code 0 
 
呵呵,工人干活完成后,自动将发生的事件汇报给老板。
 
当然,如果工人很多,每个人都汇报的话,老板肯定会烦,那么老板可能会下达,发生了严重问题的员工才需要汇报问题。这个时候,需要做个事件过滤。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值