参考*链接:
- 中文:http://zh.wikipedia.org/wiki/%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0
- 英文:http://en.wikipedia.org/wiki/Callback_(computer_programming)
回调通常与原始调用者处于相同的抽象层
回调函数的意义在于底层library代码中,需要调用函数,但这些函数无法在library阶段确定,所以要在application阶段由用户来定义。回调机制允许调用者在实际应用程序编写中调整底层library函数的行为。
这种机制使得library函数无法完全成为一个封闭的系统,必然给一些工具的设计中带了挑战和研究点。
这种情况在很多语言中都用例子,最典型的是OO语言中,很多设计模式中需要用到回调机制。
例子:
- 最早的例子应该就是Unix中的“信号”机制:
例如下面代码中,当程序接收到信号SIGUSR1时,将回调函数sig。void sig(int signum)
{
printf("Received signal number %d!\n", signum);
}signal(SIGUSR1, sig);
- JavaScript:几乎所有JS的程序中都用到了callback机制。
- Java:在我的研究中,目前关心Java的回调(回调广泛用于Swing和Android程序设计),例如addEventListener等。举一个Java设计模式中的例子:Observer模式
// Client端代码行:mySubject为Server端的对象,调用Server端的Register方法传入一个对象
mySubject.Register(myObserver);通过Register函数注册Observer。
// Server端代码行:Server端代码回调了Client端的Update方法(是Client端定义的)
observer.Update(message);每次发生一个事件,调用observer自己实现的Update函数。
由于Update函数是Client端设计的,因此这个函数便是回调函数。
语言机制:
很多语言都提供了一些特殊的语言机制来支持回调,详见这里。
- C/C++/Pascal:函数指针(function pointer)作为参数传入函数
- JavaScript, Lua, Python, Perl, PHP:函数对象(function object)作为参数传入函数
- C++:C++还可以通过重载括号,也就是重载函数调用操作符,来实现生成函数对象(C++ allows objects to provide their own implementation of the function call operation)
- 在缺少函数类型的参数的面向对象的程序语言中,例如Java,回调可以用传递抽象类或接口来模拟。回调的接收者会调用抽象类或接口的方法,这些方法由调用者提供实现。这样的对象通常是一些回调函数的集合,同时可能包含它所需要的数据。这种方法在实现某些设计模式时比较有用,例如访问者模式,观察者模式与策略模式。(In object-oriented programming languages without function-valued arguments, such as Java, callbacks can be simulated by passing an instance of an abstract class or interface, of which the receiver will call one or more methods, while the calling end provides a concrete implementation. Such objects are effectively a bundle of callbacks, plus the data they need to manipulate. They are useful in implementing various design patterns such as Visitor, Observer, and Strategy.)