1 理解
编程分为两类:系统编程(库/函数),应用编程(应用/函数)。
一般,库函数会提供 API(接口),拿过来直接用就好,但是有时候为了更加灵活的编程
,有些库函数会要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。这个被传入的,后又被调用的函数
,称为回调函数
旅馆提供
叫醒服务
,但是要求旅客自己决定叫醒的方法。可以是打客房电话,也可以是派服务员去敲门,睡得死怕耽误事的,还可以要求往自己头上浇盆水。这里,“叫醒”这个行为是旅馆提供的,相当于库函数
,但是叫醒的方式
是由旅客决定并告诉旅馆的,也就是回调函数
。而旅客告诉旅馆怎么叫醒自己的动作,也就是把回调函数传入库函数的动作,称为登记回调函数(to register a callback function)
— 这个就是具体连接 旅客和旅馆的函数
老板让员工做事情,做完通知老板,老板根据员工完成的情况做后续安排
员工--->库函数(旅馆)---中间函数
:无论是哪个老板,安排什么任务,都是员工做
事情(接口)
老板(旅客)---回调函数
旅客告诉旅馆怎么叫醒自己的动作 —>在回调函数里定义的完成事情的方法
2 具体解析
B实现回调接口,A使用B的引用,因为B本身就是个接口,是让A使用的
A让B做事情
- 1
接口
首先,事情单独抽象出来,成为一个接口
,接口包括,A让B做什么,需要得到什么结果(在参数里定义)
doHomeWork(String question,String answer);
void yes();
void no();
- 2
B中间函数(本质是个接口,只不过接口的功能自己定义的)
B做事情,B是库函数(中间函数),负责提供接口的,把事情做好,作为一个接口(引用),供A调用 —(因为A让B做事情,B就是个接口,A使用B接口,事情就完成了) — 和一般接口不同的是,B接口不是系统提供的,是根据 A提供的接口的引用,自己写的B的实质就是个接口,B使用接口作为引用,实现A要求的功能,A拿来B(接口)就可以实现想要的功能
getAnswer(String homework,DoHomeWork someone);
doSomething(ProgressOfWork progressOfWork,String event);
- 3
A(回调函数)
回调函数必须实现回调接口,并且实现登记回调函数,即A让B做事情的完整实现逻辑,就应该定义在A这个回调函数里面
,B就是个接口,供A使用的,那A让B做事情,A的方法里一定有 (事情,B的引用)这两个参数
// 在构造函数里初始化B
public Boss(Employee employee) {
this.employee = employee;
}
// 在方法里得到B做事情的方法,这个在 起始函数里要用,
public void doEvent(String event){
// 将当前对象传给员工,员工才可以回调
employee.doSomething(this,event);
}
// 用匿名内部类的形式实现B的实例
ask( final String homework, final RoomMate roomMate){
roomMate.getAnswer(homework, Student.this);
}
- 4 在起始函数里调用
B是一个接口,A让B做事情,那么A函数里一定包含B的引用了,在起始函数里直接调用即可,
起始函数不定义具体的方法
3 具体实例
3.1 Boss通知员工做事情,员工完成任务之后告诉Boss完成情况。
1 接口
public interface ProgressOfWork {
public abstract void yes();
public abstract void no();
}
2 员工(B,中间函数)
public class Employee {
public Employee(){}
// 完成 Boss交代的事情,回调接口作为参数传过来
public void doSomething(ProgressOfWork progressOfWork,String event){
String flag = null;
System.out.println("Employee:doingWork:"+event);
// 根据完成的情况,通知 Boss,即回调接口
System.out.println("Employee:finish the work!");
flag = "finish";
if(flag.equals("finish")){
progressOfWork.yes();
}
System.out.println("Employee:not finish the work"+event);
flag="notFinish";
if(flag.equals("notFinish")){
progressOfWork.no();
}
}
}
3 老板A(回调函数)
// Boss 需要实现 回调的接口
public class Boss implements ProgressOfWork {
// 传入一个员工对象
private Employee employee;
// 构造函数里面进行初始化
public Boss(Employee employee){
this.employee = employee;
}
// 告诉员工要做什么事情 --- 登记回调方法
public void doEvent(String event){
System.out.println("Boss:"+event);
// 将当前对象传给员工,员工才可以回调
employee.doSomething(this,event);
}
// 员工完成事情后的回调方法
@Override
public void yes() {
System.out.println("Boss:Work Well Doing");
}
@Override
public void no() {
System.out.println("Boss:not finish work");
}
}
4 起始函数
public class Test {
public static void main(String[] args) {
Employee employee = new Employee();
Boss boss = new Boss(employee);
boss.doEvent("write aaaaaaa");
}
}
3.2 A让室友帮忙做作业 — 使用匿名内部类实现
1 接口
public interface DoHomeWork {
public abstract void doHomeWork(String question,String answer);
}
2 室友(中间函数,接口)
public class RoomMate {
public void getAnswer(String homework,DoHomeWork someone){
if("1+1=?".equals(homework)){
someone.doHomeWork(homework,"2");
}else if("当x趋向于0,sin(x)/x=?".equals(homework)){
System.out.println("思考:");
for(int i=1;i<=3;i++){
System.out.println(i+"秒");
try{
TimeUnit.SECONDS.sleep(3);
}catch (InterruptedException e){
e.printStackTrace();
}
}
System.out.println("经过思考得出结果:");
someone.doHomeWork(homework,"1");
} else{
someone.doHomeWork(homework,"空白");
}
}
}
3 学生(回调函数)
public class Student implements DoHomeWork {
@Override
public void doHomeWork(String question, String answer) {
System.out.println("作业本");
if(answer !=null){
System.out.println("作业:"+question+"答案:"+answer);
}else{
System.out.println("作业:"+question+"答案:"+"空白");
}
}
// 具体实现,登记回调函数
public void ask(final String homework,final RoomMate roomMate){
new Thread(new Runnable() {
@Override
public void run() {
roomMate.getAnswer(homework,Student.this);
}
}).start();
goHome();
}
private void goHome() {
System.out.println("我回家了...好室友,帮我写一下作业");
}
}
4 起始函数
public class DoWork {
public static void main(String[] args) {
Student student = new Student();
String homewok = "当x趋向于0,sin(x)/x=?";
student.ask(homewok,new RoomMate());
}
}