正確理解回調函數

下面是某位大神對回調的解釋

  所謂回調,就是客戶程序client調用服務程序server中的某個函數functionA,然後server又在某個時候反過來調用client中的某個函數functionB,對於client來說,這個functionB便叫做回調函數。例如Win32下的窗口過程函數就是一個典型的回調函數。一般說來,client不會自己調用functionB,client提供functionB的目的就是讓server來調用它,而且是client不得不提供。由於server並不知道client提供的functionB姓甚名誰,所以server會約定functionB的接口規範(函數原型),然後由client提前通過server的一個函數register告訴server自己將要使用functionB函數,這個過程稱爲回調函數的註冊,Register稱爲註冊函數。Web Service以及Java的RMI都用到回調機制,可以訪問遠程服務器程序。

爲了弄明白回調函數的奧妙,首先提出三個問題:

1.        回調函數是什麼東西?

2.        回調函數怎麼開發,怎麼使用?

3.        回調函數的作用,應該在什麼情況下使用? 

*******************************************************************************

其實回調就是一種利用函數指針進行函數調用的過程,正面是一些對回調函數的解釋:

1.爲什麼要用回調呢?比如我要寫一個子模塊給你用,   來接收遠程socket發來的命令.當我接收到命令後,   需要調用你的主模塊的函數,   來進行相應的處理.但是我不知道你要用哪個函數來處理這個命令,     我也不知道你的主模塊是什麼.cpp或者.h,   或者說,   我根本不用關心你在主模塊裏怎麼處理它,   也不應該關心用什麼函數處理它......   怎麼辦?

使用回調!

 

2.使用回調函數實際上就是在調用某個函數(通常是API函數)時,將自己的一個函數(這個函數爲回調函數)的地址作爲參數傳遞給那個函數。而那個函數在需要的時候,利用傳遞的地址調用回調函數,這時你可以利用這個機會在回調函數中處理消息或完成一定的操作。

 

3.回調函數,就是由你自己寫的。你需要調用另外一個函數,而這個函數的其中一個參數,就是你的這個回調函數名。這樣,系統在必要的時候,就會調用你寫的回調函數,這樣你就可以在回調函數裏完成你要做的事。

 

4.回調函數是應用程序提供給Windows系統DLL或其它DLL調用的函數,一般用於截獲消息、獲取系統信息或處理異步事件。應用程序把回調函數的地址指針告訴DLL,而DLL在適當的時候會調用該函數。回調函數必須遵守事先規定好的參數格式和傳遞方式,否則DLL一調用它就會引起程序或系統的崩潰。通常情況下,回調函數採用標準WindowsAPI的調用方式,即__stdcall,當然,DLL編制者可以自己定義調用方式,但客戶程序也必須遵守相同的規定。在__stdcall方式下,函數的參數按從右到左的順序壓入堆棧,除了明確指明是指針或引用外,參數都按值傳遞,函數返回之前自己負責把參數從堆棧中彈出。


總結一下就一句話:回調函數就是函數指針的一種用法。  

*********************************************************************

一個很簡單的回調函數:

#include <stdio.h>
 
void printWelcome(int len)
{
       printf("歡迎歡迎 -- %d/n", len);
}
 
void printGoodbye(int len)
{
       printf("送客送客 -- %d/n", len);
}
 
void callback(int times, void (* print)(int))
{
       int i;
       for (i = 0; i < times; ++i)
       {
              print(i);
       }
       printf("/n我不知道你是迎客還是送客!/n/n");
}
void main(void)
{
       callback(10, printWelcome);
       callback(10, printGoodbye);
       printWelcome(5);
}

上面的代碼沒有被任何系統函數調用,原來回調函數就這麼簡單

在C/C++中可以通過函數指針來實現回調函數,但是在Java中沒有指針,那Java中如何實現回調函數呢?可以通過接口來實現,下面就是一個實例

package cn.org.lion;
class Caller {
 public CallInterface mInterface;
 
 //註冊函數
 public void register(CallInterface mInterface)
 {
  this.mInterface = mInterface;
 }
 
 //通過mInterface對象調用(回調)相應的函數
 public void callBack_1()
 {
  this.mInterface.method_1();
 }
 public void callBack_2(){
  this.mInterface.method_2();
 }
}

//定義回調函數的接口,該接口中規定了回調函數的聲明格式,可根據定義多個回調方法

interface CallInterface
{
 public void method_1();
 public void method_2();
}

//實現接口 CallInterface,根據自己的需要實現自己的回調函數,不用管別的類怎麼實現

class MyClass_1 implements CallInterface{
 
 public void method_1(){
  System.out.println("111111 MyClass_1's method_1() called");
 }
 public void method_2(){
  System.out.println("222222 MyClass_1's method_2() called");
 }
}

//實現接口 CallInterface,根據自己的需要實現自己的回調函數,不用管別的類怎麼實現

class MyClass_2 implements CallInterface{
 
 public void method_1(){
  System.out.println("------ MyClass_2's method_1() called");
 }
 public void method_2(){
  System.out.println("****** MyClass_2's method_2() called");
 }
}

//測試類

public class TestCallBack{
 
 public static void main(String args[]){
 
  Caller caller = new Caller();
  Caller caller1 = new Caller();
 
  caller.register(new MyClass_1());
  caller1.register(new MyClass_2());
 
  caller.callBack_1();
  caller.callBack_2();
  caller1.callBack_1();
  caller1.callBack_2();
 }
}



發佈了117 篇原創文章 · 獲贊 35 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章