回调机制深入剖析

来源:互联网 发布:开源中国 cms 编辑:程序博客网 时间:2024/05/01 01:30

问题的提出

什么是回调机制?采用回调机制有什么好处?不同的语言,如C,C++,Java等都有哪些措施来支持这种回调机制?

要回答上述问题,我们需要先回答这样一个问题:为什么需要函数调用?又为什么需要函数?!

 

是的,如果你够厉害,你都不需要函数,所以也就不需要函数调用,也就更不需要回调函数这个东西了!从头到尾,也许,一个Main函数就可以搞定所有的事情。。。

简单的函数调用

从原理上来说,的确可以这样做,远古时代的机器码,汇编代码不都是这样过来的吗?!但是,实际的情况是,你必须要函数,原因是:随着软件的代码量的增加,你必须要有一种结构化,可控的,可理解(。。。等等好处)的方式来管理你的代码,所以,函数就这样诞生了。

有了函数,也就有了调用者(Caller)和被调者(Callee)的概念,使用方式如下图所示:

 

这种使用方式很简单,只要学过任何一门高级语言的人都能理解。

示例代码

Void Caller()

{

         Callee(Para para1, …)

}

简单函数调用的局限性

下面说说这种调用方式的局限性,以此来引出回调函数的概念,并说明回调函数所能带来的在程序设计上的灵活性。

简单的函数调用具有以下几个缺点:

1.      Callee只能从Caller那里得到para1等一些少量的参数信息,它(Callee)不能够感知到Caller的存在。这时候,如果我们希望Callee能够在其运行时,能够知道Caller在哪里,并且能够利用Caller的一些资源(比如,Caller的一些功能函数【这就是回调!】),那么,这种简单的调用方式是不能满足我们的要求的

2.      示例代码中的Caller和Callee是紧密耦合的,这就很不利于扩展。比如:我们现在有多个Callee(Callee1,Callee2,…,),我们希望能够在运行时,根据不同的外部变化的条件来决定调用哪个具体的Callee,以获得更大的灵活性。

回调函数

针对上述两个缺点,回调机制能够很好的帮我们解决这些问题。而在不同的语言上,回调机制的表现形式也有所不同,总结如下:

C:   函数指针

C++:  函数指针,函数对象,基类或抽象类(多态机制)

Java:抽象类,接口

具体的实现代码,可参看我的另外两篇博文:

http://blog.csdn.net/sjtu_huang/article/details/6768080

http://blog.csdn.net/sjtu_huang/article/details/6768046

 

其原理图如下所示:

 

更进一步:异步回调机制

以上几节所讲的回调机制,其实指的都是同步回调机制,同步的含义在于:Caller对Callee的调用,以及Callee对Caller.fun()的调用,只有在调用完成,即函数返回以后,调用方的程序才能够继续往下执行。这个时候,如果Callee的调用是一个很耗时的操作(如IO操作),则将严重影响Caller的执行,造成对Caller的阻塞。

于是,我们希望得到这样一种机制:Caller在告诉Callee必须完成Caller.fun()中的任务后,就可以不去管Callee啥时执行以及啥时完成的事情,而是可以继续执行Caller自身的任务。只有等到Callee完成任务,并通知了Caller后,Caller才回来对Callee的操作后的结果进行进一步的处理,这样的话,Caller就能够避免被阻塞,而不能保证有效响应时间的困扰。当然,要实现这种机制,首先需要满足以下两个要求:

1:这种机制只能是在多进程或多线程的情况下才能实现

2:Caller的之后执行的代码并不依赖于Callee的调用及其调用结果

 

满足了上述两个要求以后,我们就可以使用一种更高级的调用机制:异步调用机制来满足上述要求。

异步调用机制简述

异步调用在应用程序框架中具有广泛的应用,并且特指多线程情况下。它同Windows的消息循环机制,消息响应,消息队列,事件驱动机制以及设计模式中的观察者模式等都是紧密相关的。


原创粉丝点击