• 回调函数(callback)浅析


    编程一段时间之后,都会或多或少的接触到“回调函数”的概念,我对这个概念的理解也是浅尝辄止,就此分享一些浅见。

    "软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。同步调用是三者当中最简单的,而回调又常常是异步调用的基础,因此,下面我们着重讨论回调机制在不同软件架构中的实现。"[1]

    关于回调,我的个人感觉就是B定义了接口或者是模板,A作为调用者自己实现它,但是A将自己的实现嵌入了B的环境中。抽象一点,其实就是A的定义域嵌入到B的执行域。大部分时候,这两个是在一起的。

    Java语言实现

    //: innerclasses/Callbacks.java
    // Using inner classes for callbacks
    package innerclasses;
    import static net.mindview.util.Print.*;
    
    interface Incrementable {
      void increment();
    }
    
    // Very simple to just implement the interface:
    class Callee1 implements Incrementable {
      private int i = 0;
      public void increment() {
        i++;
        print(i);
      }
    }	
    
    class MyIncrement {
      public void increment() { print("Other operation"); }
      static void f(MyIncrement mi) { mi.increment(); }
    }	
    
    // If your class must implement increment() in
    // some other way, you must use an inner class:
    class Callee2 extends MyIncrement {
      private int i = 0;
      public void increment() {
        super.increment();
        i++;
        print(i);
      }
      private class Closure implements Incrementable {
        public void increment() {
          // Specify outer-class method, otherwise
          // you'd get an infinite recursion:
          Callee2.this.increment();
        }
      }
      Incrementable getCallbackReference() {
        return new Closure();
      }
    }	
    
    class Caller {
      private Incrementable callbackReference;
      Caller(Incrementable cbh) { callbackReference = cbh; }
      void go() { callbackReference.increment(); }
    }
    
    public class Callbacks {
      public static void main(String[] args) {
        Callee1 c1 = new Callee1();
        Callee2 c2 = new Callee2();
        MyIncrement.f(c2);
        Caller caller1 = new Caller(c1);
        Caller caller2 = new Caller(c2.getCallbackReference());
        caller1.go();
        caller1.go();
        caller2.go();
        caller2.go();
      }	
    } /* Output:
    Other operation
    1
    1
    2
    Other operation
    2
    Other operation
    3
    *///:~
    
    上述例子来自“Think in Java”第四版。这里使用了内部类(inner class)和接口(interface)来实现回调。

    Perl语言实现

    use File::Find;
    
    sub create_find_callbacks_that_sum_the_size {
    	my $total_size = 0;
    	return ( sub { $total_size += -s if -f }, sub { return $total_size } );
    }
    
    my ( $count_em, $get_results ) = create_find_callbacks_that_sum_the_size();
    
    find( $count_em, "bin" );
    
    my $total_size = &$get_results();
    
    print "total size of bin is $total_size \n";
    
    上述例子来自“Learning Perl Objects, References & Modules”,Perl里面其实用了闭包(closure)来实现了回调。

    参考:

    1. http://hi.baidu.com/zhuyipeng/blog/item/863fefdb7c736c63d1164eec.html
    2. http://blog.csdn.net/lcqtdwj/article/details/6710355
    3. http://blog.csdn.net/mac_philips/article/details/6058946

  • 相关阅读:
    ALinq Dynamic 使用指南——前言
    前端与后端分离的架构实例(三)
    前端与后端分离的架构实例(二)
    启动画面QSplashScreen鼠标点击的时候不退出
    Qt组件屏蔽鼠标激活
    Qt LNK2001错误
    QtDesigner中设定一个组件位于另一个组件上方
    QToolButton设置图片
    osgearth_package切片工具切局部影像或者高程tif无法生成切片问题;切完数据集无法显示问题
    Qt输入框添加搜索按钮,以及自动补全内容
  • 原文地址:https://www.cnblogs.com/ainima/p/6331303.html
Copyright © 2020-2023  润新知