1.概述
軟件模塊之間總是存在着一定的接口,從調用方式上,可以把他們分爲三類:同步調用、回調和異步調用。
同步調用:一種阻塞式調用,調用方要等待對方執行完畢才返回,它是一種單向調用;
回調:一種雙向調用模式,也就是說,被調用方在接口被調用時也會調用對方的接口;
異步調用:一種類似消息或事件的機制,不過它的調用方向剛好相反,接口的服務在收到某種訊息或發生某種事件時,會主動通知客戶方(即調用客戶方的接口)。
回調和異步調用的關係非常緊密:使用回調來實現異步消息的註冊,通過異步調用來實現消息的通知
所謂回調,就是客戶程序CLIENT調用服務程序SERVER中的某個函數SA(),然後SERVER又在某個時候反過來調用CLIENT中的某個函數mycallback(),對於CLIENT來說,這個mycallback便叫做回調函數。例如Win32下的窗口過程函數就是一個典型的回調函數。
一般說來,CLIENT不會自己調用mycallback,CLIENT提供mycallback的目的就是讓SERVER來調用它,而且是CLIENT不得不提供。由於SERVER並不知道CLIENT提供的mycallback叫甚名誰,所以SERVER會約定mycallback的接口規範(函數原型),然後由CLIENT提前通過SERVER的一個函數R告訴SERVER自己將要使用mycallback函數,這個過程稱爲回調函數的註冊,R稱爲註冊函數。Web SERVERervit 和Cliente以及Java的RMI都用到回調機制,可以訪問遠程服務器程序。
2.同步回調方法
開發過程:
Client
寫了一段程序,其中預留有回調函數接口,並封裝好了該程序。
Server
要讓client調用自己的程序Server中的一個方法,於是,他通過client中的接口回調自己Server中的方法。
在C/C++中,要用回調函數,被掉函數需要告訴調用者自己的指針地址,但在JAVA中沒有指針,怎麼辦?我們可以通過接口(interface)來實現定義回調函數。
首先定義一個回調接口,以便 CLIENT和SERVER進行交互。
public interface MyCallBack {
//執行回調操作的方法
void execute();
}
以下是Server端程序:
public class Server {
/**如果要執行這個方法,必須提供回調接口*/
public void testTime(MyCallBack callBack) {
...
callBack.execute(); ///進行回調操作
}
}
以下是client端程序:
客戶端必須實現規定的接口,被調用的對象才能回調本對象中的方法。
public class Client implements MyCallBack{
Server server = new Server();
/**如果契約,必須定義一個規定的函數,以實現被調
* 這個方法,本對象一般不執行,只用於回調
*/
public void execute(){
System.out.println("我被回調了");
}
/**將本對象以接口的方式傳遞過去,server處理完後執行接口中的方法,實現回調*/
public void callServer(){
server.testTime(this);
}
}
public static void main(String[] args) {
Client client = new Client();
client.callServer();
}
步調回調函數使用場景
某天,我打電話向你請教問題,當然是個難題,你一時想不出解決方法,我又不能拿着電話在那裏傻等,於是我們約定:等你想出辦法後打手機通知我,這樣,我就掛掉電話辦其它事情去了。過了XX分鐘,我的手機響了,你興高采烈的說問題已經搞定,應該如此這般處理。故事到此結束。這個例子說明了“異步+回調”的編程模式。其中,你後來打手機告訴我結果便是一個“回調”過程;我的手機號碼必須在以前告訴你,這便是註冊回調函數;我的手機號碼應該有效並且手機能夠接收到你的呼叫,這是回調函數必須符合接口規範。