今天在学习Android的时候,突然看到“回调函数”这个关键字,但是却在脑海中找不到相应的映射。于是去一些CSDN博客上恶补了关于回调函数的知识。
后来为了加深理解,编写了3个例子(第一个是纯回调函数;第二个是观察者模式,里面应用了回调函数的思想;第三个是代理模式,也和回调很类似),现在记录我今天的学习。
第一部分:关于回调函数的理解(具体定义网上都类似,我这里用编程来实践)
定义一个程序A类:
public class A {
//定义回调对象,因为实现回调函数的具体类肯定会实现CallBackInterface接口
//所以将回调对象的类型设为接口类型
private CallBackInterface cbInterface;
//设置回调对象的函数
public void setCallFunc(CallBackInterface cbInterface)
{
this.cbInterface=cbInterface;
}
//调用回调函数,回调函数在回调接口里面预留
public void call()
{
//通过回调对象调用回调函数
if(cbInterface!=null)//为了程序更加严谨
{
cbInterface.callBack();
}
}
}
定义A类里面的回调接口:
/**回调接口里面定义回调函数*/
public interface CallBackInterface {
public void callBack();
}
定义一个程序B类(实现回调接口):
/**具体实现回调函数的类*/
public class B implements CallBackInterface{
@Override
public void callBack() {
//回调函数具体的实现
System.out.println("具体回调函数的实现,由B类来实现!");
}
}
测试类:
/**测试回调函数的程序入口*/
public class Test {
public static void main(String[] args) {
/**方法一,回调函数具体的实现类B类是一个具体的类*/
A a1=new A();
B b1=new B();
a1.setCallFunc(b1);
a1.call();
/**方法二,回调函数具体的实现由匿名类完成*/
A a2=new A();
a2.setCallFunc(new CallBackInterface()
{
//匿名类的回调函数实现方法
@Override
public void callBack() {
System.out.println("由匿名类实现A的回调函数!");
}
});
a2.call();
}
}
效果图:
总的来说:先定义一个回调接口(里面声明回调函数),然后程序B实现该接口,定义具体的函数的内容,最后程序A里面添加回调对象B。这时就可以通过A的函数来调用B里面的回调方法(实际上还是A里面通过B的对象来调用B的方法)
第二部分:观察者模式(因为观察者模式应用了回调函数的思想)
定义抽象的主题角色:
//抽象的主题角色---抽象的被观察对象,里面生命方法(移除,添加,通知观察者)
public interface Watched {
public void addWatcher(Watcher watcher);
public void removeWatcher(Watcher watcher);
public void notifyWatchers(String str);
}
定义抽象的观察者:
//抽象的观察者
public interface Watcher {
public void update(String str);
}
定义具体的主题角色:
//定义具体的主题对象,类似与回调例子中的A类
public class ConcreteWatched implements Watched{
//存放观察者
private List<Watcher> list=new ArrayList<Watcher>();
@Override
public void addWatcher(Watcher watcher) {
list.add(watcher);
}
@Override
public void removeWatcher(Watcher watcher) {
list.remove(watcher);
}
//这个函数相当于A类里面的call()函数,用来调用回调函数update(String str)
@Override
public void notifyWatchers(String str) {
for(Watcher watcher:list)
{
//调用回调函数
watcher.update(str);
}
}
}
定义具体的观察者:
//定义具体的观察者---类似与回调函数例子中的B类(实现具体的回调功能),这里面update(String str)就是一个回调函数
public class ConcreteWatcher implements Watcher{
@Override
public void update(String str) {
//具体功能的实现,这里只是简单的输出
System.out.println(str);
}
}
测试程序:
/**测试观察者模式的程序入口*/
public class Test {
public static void main(String[] args) {
//添加主题对象-用来调用回调函数
Watched watched_01 = new ConcreteWatched();
//添加观察者-用来定义回调函数的具体实现
Watcher watcher_boy1 = new ConcreteWatcher();
Watcher watcher_boy2 = new ConcreteWatcher();
Watcher watcher_boy3 = new ConcreteWatcher();
//主题对象添加对应的观察者-添加回调对象
watched_01.addWatcher(watcher_boy1);
watched_01.addWatcher(watcher_boy2);
watched_01.addWatcher(watcher_boy3);
//主题对象通知所有的观察对象-调用回调函数
watched_01.notifyWatchers("开心");
}
}
效果图:
第三部分:代理模式(注意大致思路)
大致理解:C需要B的服务,而B通过安排A给C提供服务。其中B是被代理者(委托人),被代理类主要是接活,以及交给代理者去干活。而代理类和被代理类本身实现同一个接口。
这里以项目经理安排程序员给客户提供服务为例子
声明被代理类与代理类的共同接口(共同技能):
//抽象角色-程序员,声明被代理对象和代理对象的共同接口
public interface KindProgrammer {
//共同的技能编程
//不同之处在于,CodeProgrammer是自己编程,而ProjectManager是安排CodeProgrammer编程
public void programing();
}
定一个个具体的代理类(具体编程人员):
/**定义一个具体的代理类---具体编写程序的程序员*/
public class CodeProgrammer implements KindProgrammer{
//这个方法类似与回调函数,由CodeProgrammer具体实现,
//由ProjectManager通过调用CodeProgrammer对象来执行.
//与回调函数有点区别的就是,在那个回调实例中,A类没有必要和B类实现同一个接口
@Override
public void programing() {
System.out.println("我是一名程序员,我正在编程!");
}
}
定一个具体的被代理类(委托类,项目经理):
/**定义一个被代理类,即委托人(接活的经理)*/
public class ProjectManager implements KindProgrammer{
//定义代理对象
private KindProgrammer kindProgrammer;
//设置具体的代理对象
public void setAgency(KindProgrammer kindProgrammer)
{
this.kindProgrammer=kindProgrammer;
}
//实现具体的方法,实际上是通过代理对象来实现具体的功能
@Override
public void programing() {
System.out.println("我是一名项目经理,现在我安排一个程序员编程!");
//其实这里用到了多态
if(kindProgrammer!=null)//为了程序更加严谨
{
this.kindProgrammer.programing();
}
}
}
测试程序(客户):
/**代理模式例子的入口,从客户需求出发*/
public class Client {
public static void main(String[] args) {
//客户的一个项目需要项目经理编程实现
//现在先找到对应的项目经理
ProjectManager projectManager=new ProjectManager();
//项目经理安排一个程序员来编程完成该项目
projectManager.setAgency(new CodeProgrammer());
//表面上是项目经理编程,实际是程序员在编程
projectManager.programing();
}
}
效果图:
总结:通过编程实践,对回调函数的理解更加深刻了。
一下是完整工程的链接:http://download.csdn.net/detail/u010979495/8064967