回调函数 java实现

回调函数 java实现

前言

关于回调函数,之前自己在工作和日常的学习中其实已经在不知不觉中使用过许多次了。无论是已有框架的使用,还是自己在代码中的逻辑实现其实很多时候都用到了回调。但使用归使用,缺乏足够的认识和理解,那么平常自己的使用中确实可能很多时候理解不深刻。所以在此简单的说一下自己的理解。

使用场景1 (同步回调)

public class Man {

    GirlFriend girlFriend;

    public Man(GirlFriend girlFriend){
        this.girlFriend=girlFriend;
    }

    public void coding(){
        System.out.println("程序员男朋友coding中,让女朋友帮忙买一双篮球鞋..");
        girlFriend.cost(this,1000);
    }

    //回调函数
    public void returnMoney(int money) {
        System.out.printf("程序员收到了女朋友用剩下的money:%s\n",money);
    //其他逻辑..例如程序员自己买鼠标,键盘  buyKeyBoard(money); buyProgrammingBook(money);
    }
}
public class GirlFriend {

    public void cost(Man man, int money) {
        System.out.printf("女朋友收到了 来自程序员男朋友的:%s元钱\n", money);
        System.out.println("女朋友 买了一件衣服:-300");
        System.out.println("女朋友 买了一箱零食:-200");
        System.out.println("女朋友 买了一双鞋子:-499");
        man.returnMoney(money+500);
    }
}
public class Client {

    public static void main(String[] args) throws InterruptedException {
        Man man = new Man(new GirlFriend());
        man.coding();
    }
}

//结果如下
程序员男朋友coding中,让女朋友帮忙买一双篮球鞋..
女朋友收到了 来自程序员男朋友的:1000元钱
女朋友 买了一件衣服:-300
女朋友 买了一箱零食:-200
女朋友 买了一双鞋子:-499
程序员收到了女朋友用剩下的money:1500

这是一种同步的回调,程序员必须等女朋友用完money之后,女朋友才会把剩下的money还给程序员,此时程序员才会知道多少钱。

流程是:线性执行的,阻塞的。

这个例子其实仅仅只能用做实例,实际效果不大。同步回调的关键在于,对象A调用对象B的方法,而在对象B的方法中持有对象A的引用,并且在对象B的方法中会调用对象A的其他方法。其他方法就是returnMoney方法。

为什么会认为本例的效果不大呢,这并不是说同步回调没什么用。

**我觉得同步回调的一个很大的作用就是,更加清楚的实现了面向对象的概念。**程序员就是写代码,然后女朋友就负责花程序员的money(笑,程序员他不香吗)。

在女朋友花完钱之后,在程序员这个类里面可以调用一些程序员自身的方法。从概念上更清楚一点。

同步回调的另外一种使用方式

在上面这个例子中,returnMoney是属于Man类的一个成员方法,逻辑是写死的。并不动态。所以用接口来使用是另外一种方式。

还是那个重点 B拥有A的引用,A调用B的方法时,因为B持有A的引用,所以可以调用A的其他方法,A的其他方法就是回调。

public interface sleep {

   sleep(int sleepTime);
}

Class  Student{
    
    public void writeHomeWork(Sleep sleep){
         System.out.println("写作业...");
         System.out.println("写作业...");
         System.out.println("写作业...");
         sleep.sleep(12);
    }
}

Class Test{
    public static void main(String[]args){
        new Student(sleepTime->{
            if(sleepTime>11){
    		     System.out.println("太晚了,直接去睡觉吧..ZZZ");
            }else{
                 System.out.println("去洗澡....");
    		     System.out.println("去睡觉吧..ZZZ");
            }
        });
    }
}

在本例中Student持有Sleep接口的引用,在接口的特性下,使得我们可以在main方法中直接书写 "完成作业之后"的相关事情。此时的“对象A”其实是Sleep接口,

“对象B”是Student类,Student类持有Sleep引用,关键点在于此时的调用方不应当是“对象A”了,而是main方法,所以我们在使用接口的情况下,可以在main方法直接写回调之后的逻辑

使用场景1 (异步回调)

异步回调与同步回调其实还是那个老生常谈的问题,阻塞与非阻塞。

之前的例子里,程序员给女朋友money之后,需要等待女朋友花了钱之后,拿到剩下的钱,才能去买键盘和鼠标。不能钱都没拿到就去买键盘。这在本例中是科学的。但是还有其他的使用场景。

比如你去上午咨询学校老师问题。老师告诉你下午给你答案,到时候通知你。那么上午到下午的这段时间你要做其他的事情,等到下午老师通知你的时候,你再和老师讨论。

实现起来其实几乎没有什么区别。关键是使用场景的考虑。

老师在想答案的这段时间,是需要新开一个线程的。不能阻塞你做别的事情。

如下例:

import java.util.concurrent.TimeUnit;

public class Student {
    Teacher teacher;

    public Student(Teacher teacher) {
        this.teacher=teacher;
    }

    public void askQuestion(){

        String question="先有鸡还是先有蛋?";
        teacher.resolve(this,question);
        System.out.println(Thread.currentThread().getName()+"学生去打篮球");
        System.out.println(Thread.currentThread().getName()+"学生去吃饭");
        System.out.println(Thread.currentThread().getName()+"学生去看书");
    }

    public void phoneCallBack(String answer){
        System.out.println(Thread.currentThread().getName()+"老师的答案是:"+answer);
    }


   static class Teacher{

        public void resolve(Student student,String question) {
            new Thread(()->{
                try {
                    System.out.printf("                    %s老师开始思考问题1:%s\n",Thread.currentThread().getName(),question);
                    System.out.printf("                    %s老师开始思考问题1:%s\n",Thread.currentThread().getName(),question);
                    System.out.printf("                    %s老师开始思考问题1:%s\n",Thread.currentThread().getName(),question);
                    TimeUnit.SECONDS.sleep(3);
                    student.phoneCallBack("滚");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

    public static void main(String[] args) {
        Student student=new Student(new Teacher());
        student.askQuestion();
    }
}

//结果
main学生去打篮球
main学生去吃饭
main学生去看书
                    Thread-0老师开始思考问题1:先有鸡还是先有蛋?
                    Thread-0老师开始思考问题1:先有鸡还是先有蛋?
                    Thread-0老师开始思考问题1:先有鸡还是先有蛋?
Thread-0老师的答案是:滚

在本例子老师思考的时间里,是另外开了一个线程的。并没有阻塞学生此时处于的main线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值