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