小秋的家

          home

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            1 Posts :: 91 Stories :: 17 Comments :: 0 Trackbacks

          所謂回調(diào),就是客戶程序C調(diào)用服務(wù)程序S中的某個函數(shù)SA,然后S又在某個時候反過來調(diào)用C中的某個函數(shù)CB, 對于C來說,這個CB便叫做回調(diào)函數(shù)。例如Win32下的窗口過程函數(shù)就是一個典型的回調(diào)函數(shù)。一般說來,C不會自己調(diào)用CB,C提供CB的目的就是讓S 來調(diào)用它,而且是C不得不提供。由于S并不知道C提供的CB姓甚名誰,所以S會約定B的接口規(guī)范(函數(shù)原型),然后由C提前通過S的一個函數(shù)R告訴S自己 將要使用CB函數(shù),這個過程稱為回調(diào)函數(shù)的注冊,R稱為注冊函數(shù)。Web Service以及Java的RMI都用到回調(diào)機(jī)制,可以訪問遠(yuǎn)程服務(wù)器程序。


          一個通俗的例子。某天,我打電話向你請教問題,當(dāng)然是個難題,^_^,你一時想不出解決方法,我又不能拿著電話在那里傻等,于是我們約 定:等你想出辦法后打手機(jī)通知我,這樣,我就掛掉電話辦其它事情去了。過了XX分鐘,我的手機(jī)響了,你興高采烈的說問題已經(jīng)搞定,應(yīng)該如此這般處理。故事 到此結(jié)束。這個例子說明了“異步+回調(diào)”的編程模式。


          熟悉MS-Windows和X Windows事件驅(qū)動設(shè)計模式的開發(fā)人員,通常是把一個方法的指針傳遞給事件源,當(dāng)某一事件發(fā)生時來調(diào)用這個方法(也稱為“回調(diào)”)。Java的面向?qū)ο蟮哪P湍壳安恢С址椒ㄖ羔槪坪醪荒苁褂眠@種方便的機(jī)制。

          Java支持interface,通過interface可以實(shí)現(xiàn)相同的回調(diào)。其訣竅就在于定義一個簡單的interface,申明一個被希望回調(diào)的方法。

          例如,假定當(dāng)某一事件發(fā)生時會得到通知,我們可以定義一個interface:
          1 public interface InterestingEvent {
          2     // 這只是一個普通的方法,可以接收參數(shù)、也可以返回值
          3     public void interestingEvent();
          4 }
          這樣我們就有了任何一個實(shí)現(xiàn)了這個接口類對象的手柄grip。

          當(dāng)一事件發(fā)生時,需要通知實(shí)現(xiàn)InterestingEvent 接口的對象,并調(diào)用interestingEvent() 方法。
           1 class EventNotifier {
           2     private InterestingEvent ie;
           3     private boolean somethingHappened;
           4     public EventNotifier(InterestingEvent event) {
           5         ie = event;
           6         somethingHappened = false;
           7     }
           8     public void doWork() {
           9         if (somethingHappened) {
          10             // 事件發(fā)生時,通過調(diào)用接口的這個方法來通知
          11             ie.interestingEvent();
          12         }        
          13     }
          14 }
          在這個例子中,用somethingHappened 來標(biāo)志事件是否發(fā)生。

          希望接收事件通知的類必須要實(shí)現(xiàn)InterestingEvent 接口,而且要把自己的引用傳遞給事件的通知者。
           1 public class CallMe implements InterestingEvent {
           2     private EventNotifier en;
           3     public CallMe() {
           4         // 新建一個事件通知者對象,并把自己傳遞給它
           5         en = new EventNotifier(this);
           6     }
           7     // 實(shí)現(xiàn)事件發(fā)生時,實(shí)際處理事件的方法
           8     public void interestingEvent() {
           9         // 這個事件發(fā)生了,進(jìn)行處理
          10     }
          11 }
          以上是通過一個非常簡單的例子來說明Java中的回調(diào)的實(shí)現(xiàn)。

          當(dāng)然,也可以在事件管理或事件通知者類中,通過注冊的方式來注冊多個對此事件感興趣的對象。

          1. 定義一個接口InterestingEvent ,回調(diào)方法nterestingEvent(String event) 簡單接收一個String 參數(shù)。

          1 interface InterestingEvent {
          2     public void interestingEvent(String event);
          3 }
          2. 實(shí)現(xiàn)InterestingEvent接口,事件處理類
          1 class CallMe implements InterestingEvent {
          2     private String name;
          3     public CallMe(String name){
          4         this.name = name;
          5     }    
          6     public void interestingEvent(String event) {
          7         System.out.println(name + ":[" +event  + "] happened");
          8     }
          9 }
          3. 事件管理者,或事件通知者
           1 class EventNotifier {
           2     private List<CallMe> callMes = new ArrayList<CallMe>();
           3     
           4     public void regist(CallMe callMe){
           5         callMes.add(callMe);
           6     }
           7     
           8     public void doWork(){
           9         for(CallMe callMe: callMes) {
          10             callMe.interestingEvent("sample event");
          11         }
          12     }    
          13 }
          4. 測試
           1 public class CallMeTest {
           2     public static void main(String[] args) {
           3         EventNotifier ren = new EventNotifier();
           4         CallMe a = new CallMe("CallMe A");
           5         CallMe b = new CallMe("CallMe B");
           6         // regiest
           7         ren.regist(a);
           8         ren.regist(b);
           9         
          10         // test
          11         ren.doWork();        
          12     }
          13 }



          posted on 2012-03-27 16:30 棋劍小秋 閱讀(315) 評論(0)  編輯  收藏 所屬分類: JAVA

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          主站蜘蛛池模板: 前郭尔| 灵石县| 通化市| 怀仁县| 青浦区| 襄樊市| 邢台市| 浏阳市| 泽普县| 乡宁县| 徐州市| 宿州市| 茂名市| 准格尔旗| 绵竹市| 台前县| 新津县| 松滋市| 德清县| 万全县| 科技| 西充县| 永和县| 西安市| 栾川县| 溧水县| 拉萨市| 普陀区| 大化| 通榆县| 旬阳县| 鹿泉市| 云安县| 清原| 江山市| 福贡县| 尖扎县| 喀喇| 鸡东县| 侯马市| 敦化市|