何为回调函数
所谓回调,从字面意思理解就是,当任务/事情完成之后,回过头来完成/通知接下来要执行的动作。
一个简单的例子就是(小明遇到问题不能解决,向小王求助,问题给到小王,小王可能现在有事或者需要思考一段时间才能得出答案,而小明也不会一直等着小王解决,所以对小王说,解决后通知我一声,小明就去做其他事情了,前面所提到的解决后通知我,就是回调)。
一个简单的实现
public class Ming {
public void getAnswer(String answer){
System.out.println("Ming 解决问题,得到答案为 :" + answer);
}
public void resolve(String question){
System.out.println("Ming 思考中...");
System.out.println("Ming 问题太难,求助吧");
Wang wang = new Wang(this,question);
new Thread(){
@Override
public void run() {
wang.resolve();
}
}.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Ming 看来要等很久,那我也去做其他事情了");
}
public static void main(String []args){
Ming ming = new Ming();
ming.resolve("1 + 1 = ");
}
}
class Wang{
private Object object;
private String question;
public Wang(Object questioner,String question){
this.object = questioner;
this.question = question;
}
public void resolve() {
try {
System.out.println("Wang 我现在有事待会儿帮你解决,解决后通知你");
Thread.sleep(3000);
String answer = question + " 的答案为 2";
((Ming)object).getAnswer(answer);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
这是上面案例所示的最简单的代码实现,通过把回调所要通知的对象直接传入给被调用者。
这种方法实现既不优雅也存在很大的局限性。对于被调用方(可看作是提供服务方),被调用放回调时只能调用调用方的指定方法,当存在多个调用方时,调用方必须要有相同的方法名,作为被调用方的回调方法(即上述代码中的 getAnswer() 方法)。下面给出一个比较通用、优雅的写法:
public class BetterMing {
public void getAnswer(String answer){
System.out.println("BetterMing 解决问题,得到答案为 :" + answer);
}
public void resolve(String question){
System.out.println("BetterMing 思考中...");
System.out.println("BetterMing 问题太难,求助吧");
BetterWang wang = new BetterWang(question);
wang.setCallBack(new BetterWang.CallBack() {
@Override
public void resolveDone(String answer) {
getAnswer(answer);
}
});
new Thread(){
@Override
public void run() {
wang.resolve();
}
}.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("BetterMing 看来要等很久,那我也去做其他事情了");
}
public static void main(String []args){
BetterMing ming = new BetterMing();
ming.resolve("1 + 1 = ");
}
}
class BetterWang{
private CallBack callBack;
private String question;
public BetterWang(String question){
this.question = question;
}
public void setCallBack(CallBack callBack){
this.callBack = callBack;
}
interface CallBack{
void resolveDone(String answer);
}
public void resolve() {
try {
System.out.println("BetterWang 我现在有事待会儿帮你解决,解决后通知你");
Thread.sleep(3000);
String answer = question + " 的答案为 2";
if(callBack != null){
callBack.resolveDone(answer);
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
上述升级版代码,是在小王(服务提供方)创建一个接口,该接口由小明(需要服务方)实现,不管需要服务方怎样调用,服务提供方开放这个接口,实现由你决定。
举个栗子:当你住酒店时,酒店提供起床提醒服务,这个提醒有打电话、来房间唤醒等。其中你就是需要服务方,酒店时服务提供方,提醒服务是服务方开放的接口,具体实现由你决定。
由于java中直接将方法作为引用传递,所以通过内部接口的方式进行实现。
如有错误欢迎指正。