前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >什么是回调函数(CallBack)

什么是回调函数(CallBack)

作者头像
我是攻城师
发布2018-12-18 14:10:47
17.2K1
发布2018-12-18 14:10:47
举报
文章被收录于专栏:我是攻城师我是攻城师

我们先来看下维基百科的定义:

在计算机程序设计中,回调函数,或简称回调(call),是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。

这种标准的定义,大多数时候说的都比较抽象,下面我们以实际生活中的例子来讲解到底什么是回调函数。

回调函数的用途十分广泛,在各种编程语言里面都有体现,有点类似Spring里面IOC(inversion of control=控制反转)的概念,本身是一个非常简单的概念,看下面的一个例子:

假设一个场景:

老师给学生布置了作业,学生收到作业后开始写作业,写完之后通知老师查看,老师查看之后就可以回家。

回调的概念,在这里面就体现的淋漓尽致,在这里面有两个角色,一个是老师,一个是学生。老师有两个动作,第一个是布置作业,第二个是查看作业。而学生有一个动作是做作业, 那么问题来了,老师并不知道学生何时才能做完作业,所以比较优雅的解决办法是等学生的通知,也就是学生做完之后告诉老师就可以。这就是典型的回调理念。

那么在编程中,该如何体现? 从上面的分析中,可以得出来回调模式是双方互通的,老师给学生布置作业,学生做完通知老师查看作业。 关于回调,这里面还分同步回调和异步回调两种模式:

同步模式:

如果老师在放学后,给学生布置作业,然后一直等待学生完成后,才能回家,那么这种方法就是同步模式。

异步模式:

如果老师在放学后,给学生布置作业,这个时候老师并不想等待学生完成,而是直接就回家了,但告诉学生,如果完成之后发短信通知自己查看。这种方式就是异步的回调模式。

回调模式为了不影响主任务执行,一般会设计成异步任务。下面我们看下在Java中,模拟上面举的例子实现一个简单的回调,包括同步和异步两种模式:

首先,回调的方法我们最好定义成一个接口,这样便于扩展:

代码语言:javascript
复制
/***
 *通过接口定义回调函数
 */
public interface CallBack {
    //检查作业属于老师的功能,但由学生触发,故称回调
    public void checkWork();
}

然后,我们定义老师的角色:

代码语言:javascript
复制
package design_pattern.callback.demo2;
public class Teacher implements CallBack {
    private Student student;
    public Teacher(Student student) {
        this.student = student;
    }
    /***
     *  给学生分配作业
     * @param isSync true=同步回调 false=异步回调
     * @throws InterruptedException
     */
    public void assignWork(boolean isSync) throws InterruptedException {
        System.out.println("老师分配作业完成....");
        if(isSync){
            student.doWrok(this);//同步通知做作业
        }else{
            student.asynDoWrok(this);//异步通知做作业
        }
        System.out.println("老师回家了....");
    }
    @Override
    public void checkWork() {
        System.out.println("老师收到通知并查看了学生的作业!");
    }
}

上面定义的是老师角色,有两个行为,一个是布置作业,一个是检查作业,布置作业里面,在布置作业里面,老师可以选择同步回调还是异步回调。

接着我们看下学生角色如何定义:

代码语言:javascript
复制
public class Student  {
    public void doWrok(CallBack callBack) throws InterruptedException {
        System.out.println("学生开始做作业.....");
        TimeUnit.SECONDS.sleep(3);
        System.out.println("学生完成作业了,通知老师查看");
        callBack.checkWork(); //通知老师查看作业
    }
    public void asynDoWrok(CallBack callBack) throws InterruptedException {
     //通过一个线程来异步的执行任务
     Runnable runnable= new Runnable(){
            @Override
            public void run() {
                System.out.println("学生开始做作业.....");
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("学生完成作业了,通知老师查看");
                callBack.checkWork();
            }
        };
     Thread thread=new Thread(runnable);
     thread.start();
    }
}

学生角色里面只有一个行为做作业,但这里我提供了两种模式,一个是同步,一个是异步。

最后,我们来测试下:

代码语言:javascript
复制
public class AppMain {
    public static void main(String[] args) throws InterruptedException {
        Student student=new Student();//学生角色
        System.out.println("\n===============同步模式================");
        Teacher teacher=new Teacher(student);//老师角色
        //同步回调模式,老师给学生布置作业,老师等学生完成之后才能回家
        teacher.assignWork(true);
        System.out.println("\n===============异步模式================");
        //异步回调模式,老师给学生布置作业,布置完成之后就可以回家,学生完成之后会通知老师查看。
        teacher.assignWork(false);
    }
}

执行结果如下:

代码语言:javascript
复制
===============同步模式================
老师分配作业完成....
学生开始做作业.....
学生完成作业了,通知老师查看
老师收到通知并查看了学生的作业!
老师回家了....
===============异步模式================
老师分配作业完成....
老师回家了....
学生开始做作业.....
学生完成作业了,通知老师查看
老师收到通知并查看了学生的作业!

对于同步和异步两种模式的结果,在上面的输出内容里面可以非常清晰的看出来区别,也体现回调的双通模式。老师角色持有了学生对象的引用,并告诉学生做作业,而同时学生角色,也持有老师角色的引用,可以在自己完成作业后,告诉老师查看作业。

总结:

回调模式,在生活中的例子非常常见,在编程中最常见的就是各种GUI编程里面的按钮点击什么的,通过回调可以将控制权转移,配合上异步模式,可以让系统设计的更加优雅。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-11-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 我是攻城师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
短信
腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档