网上看了许多关于回调函数的例子及理解,发现很多都是为了说明回调而写的回调,当然,例子简单明了,也很能说明问题,但是要在实际中使用的时候很多人还是一头雾水。这里用我个人的理解并配上一些个人总结的例子来加以说明。
首先说一下回调函数的基本两个成员,一个是调用方,一个是被调用方。
调用方(BOSS 就叫老板吧 简称B):可以是任何有需要S服务的类,这里有一个回调方法,用于S服务类在服务过程中或服务完时调用。
在这里有两个问题:
1、S服务方法中要怎样才能调用B中的回调方法,这里只能让S持有B对象,在B调用服务方法前调用将自己对象传入到S中。2、S服务方法中要怎么知道调用B的哪个回调方法。
这里解决办法就是用接口(这里用IS表示),并在接口中定义回调方法。这样在S服务方法中就只需要持有接口类型即可,并在调用回调方法时调用接口中的回调方法就行了。有需要调用S服务的类就必须实现S服务指定的接口IS并实现里面的方法。(这里有点啰嗦,主要还是考虑基础比较差的)。
这里举个通俗的例子,也希望读者能加深接口的理解。司令B 和 间谍S例子:
间谍S只会一件事,就是看敌方有没坦克。
司令B想让间谍S去敌方阵地看看是否有坦克,现在问题来了,间谍看到坦克后要怎么通知司令呢(假设跑回来通知太慢了),于是他们想了一个办法,要让司令学会放风筝。
这里创建放风筝这个接口(IS)。并只有一个方法就是拉一下线。
并且间谍S手上永远有一根线,专门用于执行风筝的方法,这个例子里只是拉一下线。
于是司令就实现了放风筝这个接口,这样司令就有了放风筝的本领了(这个本领很强大,一旦有这个本领,就会有一只风筝在你头上飞着,并且线是放你手中的。),这个本领只有一个动作,那就是轻轻拉一下线,当然了这个风筝不拉线也一直是在飞的。
好了,现在司令B派间谍S去敌方阵地,并将S手上的线绑到司令的风筝上(引用传递给S)。
然后S就去敌方阵地了,当S发现有坦克后,于是就用手中的线执行了一下接风筝的方法(动作)。
由于线是绑在司令风筝上的,(引用引向司令这个会放风筝的人),司令就接收到了有坦克的指定,并下达了下一个作战任务(派飞机前去轰炸)。>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
不久另一个司令的间谍死了,决定借这个间谍S用一下,间谍S就说了,要用我当间谍你只要会放风筝就行了,所以,以后只要司令想让间谍去敌方阵地探情报,只要实现放风筝这个接口,并线绑到间谍手上的线上就行了。
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
1、服务类
package ex09.ex20.ex01;
public class 间谍 {
private 放风筝 f;
public 放风筝 getF() {
return f;
}
public void setF(放风筝 f) {
this.f = f;
}
public void 看敌方坦克(){
System.out.println("间谍:正在要去看敌方坦克。。。");
System.out.println("间谍:走路中.....");
System.out.println("间谍:....十分钟后发现有坦克,赶紧拉线通知司令");
f.拉线();
}
}
2、调用类,要实现约定的接口
package ex09.ex20.ex01;
public class 司令 implements 放风筝{
间谍 js = new 间谍();
@Override
public void 拉线() {
// TODO Auto-generated method stub
System.out.println("司令:间谍说有坦克,飞机去轰炸!");
}
public void 指挥战斗(){
System.out.println("司令:我正在指挥战斗,决定先派间谍去看敌方有没坦克");
js.setF(this);
js.看敌方坦克();
}
}
3、约定的接口
package ex09.ex20.ex01;
public interface 放风筝 {
public void 拉线();
}
4、测试
package ex09.ex20.ex01;
public class 总指挥 {
public static void main(String[] args) {
// TODO Auto-generated method stub
司令 sl = new 司令();
sl.指挥战斗();
}
}
这里是一个小例子,其它例子都大同小异,有的是将实现直接做为一个匿名类而已。