FUCK,网上装逼者甚众矣!
网上一堆关于JAVA函数回调的见解文章,都说自己写的明白,但没几个我看的明白的。
不如自己写一个东西,回头自己看着舒服
回调函数:定义自己百度
干嘛的?
场景就是事务A执行一个函数时,函数内部调用了事务B中的一个方法,且接下来事务A的继续要依赖于B的方法的结果返回。
FUCK,绕不绕?!网上一搜一大把这种说辞的。我也觉得绕。
我来个通俗易懂的。
热恋中的男女,晚上吃完饭看完电影要各回各家各找各妈的时候。
男孩说,虽然我们没能去啪啪啪,但是你到家了要告诉我一声,我给你提个要求,就是到家后通知我一声就好,我好安心睡觉,至于你怎么回家我不管了。
场景描述完毕,现在抽象数据模型。
这就是回调的使用,男孩要知道女孩回家的状态,但是女孩什么时候才能到家,是否安全到家他都不知道也没办法掌控,但是他和女孩说好了一个约定,就是到家后给我一个结果就好了。
什么狗屁的所谓的回调,不如说对某事件的状态监听,想要监听谁就给谁安插一个监听器进去,监听器是干啥的那就看要看主动监听的对象的意思了。
上面这个场景就是男生要监听女孩回家的状态,再通俗一点就是我是男生,我给女孩一个手机,到家了给我用这个手机联系我,是发信息还是打电话那就看我这个手机支持什么具体操作了。
那么最后抽象出来的模型就是
1男孩 class Boy
2女孩 class Girl
3手机 监听器 回调函数,继续抽象就是一个接口interface CallBackDoSomething,回调函数总是要做点事情的嘛。
好了,下面我们就要实现代码了,没有从浅到深的啰嗦,直接用项目中实际的操作展示。
1),首先我们定义接口,回家有很多中状态,就好比项目中业务是实现结果有成功失败和超时等
回家有安全到家 危险状态 又出去high三个状态
1 package com.callback2;
2
3 public interface CallBackDoSomething {
4 public void onSafe(String info);
5 public void onDanger(String info);
6 public void onGoOut(String info);
7 }
监听器有三个方法,到家的状态认为有三种,哪个发生了执行哪个回调
2),男孩要对女孩进行监听,怎么监听男孩说的算,所以接口要由男孩实现,这个逻辑很好理解。
1 package com.callback2;
2
3 public class Boy implements CallBackDoSomething{
4
5 private Girl girl;
6
7 public Boy(Girl girl){
8 System.out.println("凭空造个男生,让他有一个girl");
9 this.girl = girl;
10 }
11
12 public void whenGirlGetHomeDoSomething()
13 {
14 System.out.println("我是男生,要知道女孩到家的状态");
15 girl.tellBoyMyStatus();
16 }
17
18 @Override
19 public void onSafe(String info) {
20 // TODO Auto-generated method stub
21 System.out.println("我是男生,girl告诉我她的状态是:"+info);
22 System.out.println("我是男生,知道你安全到家我就放心了");
23 }
24
25 @Override
26 public void onDanger(String info) {
27 // TODO Auto-generated method stub
28 System.out.println("我是男生,girl告诉我她的状态是:"+info);
29 System.out.println("告诉我你在哪,我去找你");
30 }
31
32 @Override
33 public void onGoOut(String info) {
34 // TODO Auto-generated method stub
35 System.out.println("我是男生,girl告诉我她的状态是:"+info);
36 System.out.println("不要玩太晚啊");
37 }
38
39 }
那么首先作为男孩,要监听女孩,所以必须有个女孩属于自己啊,在自己这里需要private一个实例女孩出来。
3)接下来,女孩也同意男孩要求,说我听你的,到家了跟你说一声。 所以女孩要把监听器带着。监听器哪里来的呢,男孩给的。
1 package com.callback2;
2
3 public class Girl{
4
5 private CallBackDoSomething callBackDoSomeThing;
6
7 public Girl(){
8 System.out.println("凭空造个girl");
9 }
10
11 public void setCallBackDoSomething(CallBackDoSomething callBackDoSomeThing){
12 if(null != callBackDoSomeThing){
13 System.out.println("我是女生,男孩让我后告知我的状态(我拿到了boy的监听器)");
14 this.callBackDoSomeThing = callBackDoSomeThing;
15 }
16 }
17
18 public void tellBoyMyStatus(){
19 //执行回家的业务,针对业务执行结果调用不同的回调函数
20 try{
21 System.out.println("模拟回家过程,睡眠阻塞");
22 Thread.sleep(1000L);
23 }catch(Exception e){
24 e.printStackTrace();
25 }
26 //假设安全到家,业务顺利执行了
27 iHaveGetHomeSafety();
28 }
29
30 public void iHaveGetHomeSafety(){
31 System.out.println("我是女生,我的状态是我到家了");
32 callBackDoSomeThing.onSafe("我到家了");
33 }
34
35 public void iHaveGetHomeDanger(){
36 System.out.println("我是女生,我的状态是我没有安全到家");
37 callBackDoSomeThing.onSafe("我没有安全到家");
38 }
39
40 public void iHaveGetHomeGoOut(){
41 System.out.println("我是女生,我的状态是我又出去high了");
42 callBackDoSomeThing.onSafe("我又出去high了");
43 }
44
45 }
三个具体的类都抽象出来也都实现了,下面具体实测一下效果。
我实现一个面函数
1 package com.callback2;
2
3 public class CallBackMain {
4
5 public static void main(String[] args) {
6 // TODO Auto-generated method stub
7 Girl girl = new Girl();
8 Boy boy = new Boy(girl);
9
10 // girl.setCallBackDoSomething(new CallBackDoSomething() {
11 //
12 // @Override
13 // public void onSafe(String info) {
14 // // TODO Auto-generated method stub
15 // System.out.println("我是男生,girl告诉我她的状态是:"+info);
16 // System.out.println("(匿名)我是男生,知道你安全到家我就放心了");
17 // }
18 //
19 // @Override
20 // public void onGoOut(String info) {
21 // // TODO Auto-generated method stub
22 // System.out.println("我是男生,girl告诉我她的状态是:"+info);
23 // System.out.println("(匿名)不要玩太晚啊");
24 // }
25 //
26 // @Override
27 // public void onDanger(String info) {
28 // // TODO Auto-generated method stub
29 // System.out.println("我是男生,girl告诉我她的状态是:"+info);
30 // System.out.println("(匿名)告诉我你在哪,我去找你");
31 // }
32 // });
33 /*
34 * 这句set和上面的注释的一大片效果是一样的,实际使用多用上面注释的一大片那种形式
35 * 不过为了便于理解,在Boy中是实现具体的接口
36 * */
37 girl.setCallBackDoSomething(boy);
38
39 boy.whenGirlGetHomeDoSomething();
40 System.out.println("已经各回各家各找各妈了");
41 }
42
43 }
在面函数最底部三行有效代码,
第一句看到女孩接受了监听器,
然后第二句男孩开始进入监听的业务流程,
最后第三句调试输出,
三句里没有显式的调用男孩知道女孩状态后要干什么。
so,最后我们返回到原来的那句话
场景就是事务A执行一个函数时,函数内部调用了事务B中的一个方法,且接下来事务A的继续要依赖于B的方法的结果返回。
场景就是事务A执行一个函数时
翻译: boy执行whenGirlGetHomeDoSomething这个功能的时候
函数内部调用了事务B中的一个方法
翻译: whenGirlGetHomeDoSomething里面有个实例girl调用了自己的tellBoyMyStatus
且接下来事务A的继续要依赖于B的方法的结果返回
翻译:接下来就是回调的具体实现了, girl有具体结果后调用回调,boy完成最后的业务。
总结:想要监听谁(某事务的运行结果),就给谁安插一个监听器(接口的实例对象),在这个类中私有一个接口引用,并完成一个“set”方法赋值。当事务执行完毕,执行接口里面对应的方法(回调),就能将监听结果反馈给主动监听的对象。主动监听的对象去实现接口的方法。
boy是主动监听的对象,由boy实现接口
girl是被监听的对象,要安插一个接口的引用在里面,并在girl里完成“set”方法
girl完成自己的事情后,执行接口方法进行回调
逻辑就是这么个逻辑
那么实际的运行结果是什么呢?
本来在新浪里面写完了,但是排版实在垃圾,突然想到好像自己有个博客园的账号,还能登陆进来搬家来这边。
没有自己好好排版,先这么弄吧,博客园处女作。理解不对勿喷,请指正。