前几年主要在做JAVA开发,对回调接触得不多。最近几个月更多地使用了javascript和objective-c,本文总结一下我的粗浅理解
java并不是不能实现回调,只是比较麻烦,并且也不是惯用法,至少我这5年几乎没有遇到过必须使用的场景。如果一定需要的话,也可以实现:
public void doSomething(Callable callback){ // 做一些逻辑 callback.xxx();// 回调 // 做另外一些逻辑 }
而在javascript和objective-c中,特别是前者,回调就很常见了。总结起来,实现回调的主要方法有2种,分别是callback和delegate。js里callback用得比较多,而oc里两者都很常见
函数在js和oc里都是一等公民,所以实现callback很容易。在js里就是一般的function,oc用的是block
-(void) doOperation:(void(^)(FMDatabase*))block; -(void) doOperation:(void(^)(FMDatabase*))block { [db open]; block(db); [db close]; }
delegate模式在oc里用的很多,包括许多原生的API,也是使用delegate实现回调的,比如UITableViewDelegate等
-(void) doSomething { // do something [delegate someMethod]; // do something }
总的来说,这2种机制的目的,都只是提供两个对象之间通信的方式。A对象在调用B对象上的方法时,传一个回调函数作为参数,或者将自己设置为B的delegate,都使B在需要的时候,可以反过来调用A的方法
delegate的好处是比较灵活,而且由于一个对象可以被组合和继承,还可以同时作为多个对象的delegate,所以复用性也比较好
但是callback最好的一点在于,可以利用闭包的特性,因此传参特别方便,考虑下面的代码:
- (void)search:(CDVInvokedUrlCommand*)command { [printer scanPrinterStart:^(void){ // do something [command xxx]; }]; }
2种方式各有优劣,所以IOS很多的原生API,都同时提供了delegate和callback接口,让用户可以根据实际情况选择
以前我总是把异步和回调混在一起,错误地理解为:回调一定是异步的。其实并非如此
前面说了,回调只是2个对象之间通信的方式,不代表一定是同步或者异步的。具体究竟是同步还是异步,要看实现,比如下面2段代码,都采用了回调,但是前者是同步的,后者是异步的
example(function(){ console.log("called"); }); // 后续操作,将被example()调用阻塞 function example(callback){ // 耗时操作 callback(); // 耗时操作 }
-(void) test { [self example:^(void){ NSLog(@"called"); }]; // 下面的操作立刻执行,不会被example()调用阻塞 } -(void) example:(void(^)(void))callback { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ // 耗时操作 callback(); }); return; }
所以,是同步还是异步,与回调函数没有必然联系。只是由于在javascript,特别是node.js里,几乎95%的回调函数都是异步的,所以在某种程度上造成了误解
要实现2个对象之间的通信,回调和delegate都是很好的方式,由于回调可以利用闭包的特性,所以我觉得更方便一点
判断一个函数是同步的还是异步的,要看它是立刻返回,还是会长时间阻塞,与它是否接受callback function作参数无关。回调只是提供通信的机制。不过在实践中,利用回调函数实现异步调用,是一种非常常见的做法
原文:http://blog.csdn.net/kyfxbl/article/details/18321405