java接口回调、同步回调、异步回调

时间:2022-12-23 23:31:25

一、C中的回调

          回调用于层间协作,简单的说就是:下层反过来调用上层的函数。其实回调和API非常接近,他们的共性都是跨层调用的函数。但区别是

(1)API是低层提供给高层的调用,一般这个函数对高层都是已知的;

(2)回调就是该函数写在高层,低层通过一个函数指针保存这个函数,而低层通过该函数指针调用高层那个函数。


二、java中的回调

         在java编程中,要从面对对象的角度,来理解回调,而不应再从层级的角度理解回调,关于这方面的解析很少,本文旨在从理论和编程两个方面进行解释java中的回调。

        本质上说,java中的回调就是将规定一个接口,然后设计一个类(该类与接口存在关联或者依赖关系),最后,当使用这个类的时候,实现之前规定的接口,这就是java中的回调。简单的说,在Java中,通常就是编写下层的人规定一个接口,由上层来实现这个接口;然后上层就可以把这个接口的一个对象作为参数传给下层,下层就会通过那个接口来调用由上层编写的函数。

       所以,java的回调是以接口的形式实现的。从类之间的关系角度看,有关联与依赖之分。

1、关联:指一个类中使用另一个类做为成员变量。下面看代码:

public interface IHello {
	void sayHello();
}

public class Man {
	private IHello hello;//关联

	public Man(IHello hello) {
		this.hello = hello;
	}

	public void say() {
		hello.sayHello();
	}
}
测试:有两种方式:实现接口和匿名类。

public class Test implements IHello {

	@Override
	public void sayHello() {
		System.out.println("hello");
		
	}

	public static void test() {
		Man chinese = new Man(new IHello() {
			public void sayHello() {
				System.out.println("你好");
			}
		});
		chinese.say();
	}

	public static void main(String[] args) {
		test();
		Man english = new Man(new Test());
		english.say();
	}

}
 【实验结果】

hello
你好
【分析】

本例在构造函数中将接口注册到该类,当然我们也可以写一个注册函数,如下所示:

public interface IHello {
	void sayHello();
}

public class Man {
	private IHello hello;//关联

	void setCallback(IHello cb){
		hello = cb;
	}
	public void say() {
		hello.sayHello();
	}
}
测试代码:

public class Test implements IHello {

	@Override
	public void sayHello() {
		System.out.println("hello");
		
	}

	public static void main(String[] args) {
		IHello mTest = new Test();
		Man english = new Man();
		english.setCallback(mTest);
		english.say();
		
		Man chinese = new Man();
		chinese.setCallback(new IHello() {
			
			@Override
			public void sayHello() {
				System.out.println("你好");
				
			}
		});
		chinese.say();
	}
}

【实验结果】

hello
你好


2、依赖:指在一个类中的方式操作另外一个类。代码如下:

public interface IHello {
	void sayHello();
}
public class Man {
	// 依赖
	public void say(IHello hello) {
		hello.sayHello();
	}
}
测试代码:

public class Test implements IHello {

	@Override
	public void sayHello() {
		System.out.println("hello");
		
	}

	public static void test() {
		Man chinese = new Man();
		chinese.say(new IHello() {
			
			@Override
			public void sayHello() {
				System.out.println("你好");
			}
		});
	}

	public static void main(String[] args) {
		test();
		Man english = new Man();
		english.say(new Test());
	}

}

【实验结果】

hello
你好

【分析】

由以上例子可以看出:

相对于依赖来说,关联说明这两个类的关系比较强,可以在不同的方法中使用另一个类,而依赖只限于一个方法中。


3、下面再看一个复杂点的回调

public interface IServer {

	void getName4Server();

	void getOld4Server();

	void setCallback(IClient cb);

}
public class Server implements IClient {
	private IServer mClient;

	@Override
	public void showName() {
		System.out.println("tfygg");
		mClient.getOld4Server();
	}

	@Override
	public void showOld() {
		System.out.println("12");
	}

	@Override
	public void setCallback(IServer cb) {
		mClient = cb;
	}

}
public interface IClient {
	void showName();
	
	void showOld();
	
	void setCallback(IServer cb);
}
public class Client implements IServer {
	private IClient mServer;

	@Override
	public void getName4Server() {
		System.out.println("名字:");
		mServer.showName();
	}

	@Override
	public void getOld4Server() {
		System.out.println("年纪:");
		mServer.showOld();
	}

	@Override
	public void setCallback(IClient cb) {
		mServer = cb;
	}

}
测试代码:

public class Test {
	public static void main(String[] args) {
		IServer mClient = new Client();
		IClient mServer = new Server();
		mServer.setCallback(mClient);
		mClient.setCallback(mServer);

		mClient.getName4Server();
	}
}
【实验结果】

名字:
tfygg
年纪:
12

【分析】

本例是一个双向回调,从客户端发起,客户端调用服务端的获取接口,然后服务端调用客户端的显示接口。采用的是关联方式。


三、同步回调

1、回调接口

package test.AsynCallBack;

public interface AsynCallBack {
	void doCallback(String question, String answer);
}
2、Server端

package test.AsynCallBack;

import java.util.concurrent.TimeUnit;

public class Server {

    public void getAnswer(String homework, AsynCallBack someone) {
        if ("1+1=?".equals(homework)) {
            someone.doCallback(homework, "2");
        } else if("当x趋向于0,sin(x)/x =?".equals(homework)) {

            System.out.print("思考:");
            for(int i=1; i<=3; i++) {
                System.out.print(i+"秒 ");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println();
            someone.doCallback(homework, "1");
        } else {
            someone.doCallback(homework, "(空白)");
        }
    }
}

3、Client端

package test.AsynCallBack;

public class Client implements AsynCallBack {

	@Override
	public void doCallback(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 Server service) {
	
		service.getAnswer(homework, Client.this);
	
		goHome();
	}

	public void goHome() {
		System.out.println("我回家了……好室友,帮我写下作业。");
	}
}

4、测试

package test.AsynCallBack;

public class CallbackTestMain {
	public static void main(String[] args) {
		Client student = new Client();
		String homework = "当x趋向于0,sin(x)/x =?";
		student.ask(homework, new Server());
	}
}


四、异步回调

1、回调接口

package com.callback;

public interface Callback {
	void doCallback(String question, String answer);
}
2、Server端

package com.callback;

import java.util.concurrent.TimeUnit;

public class Server {

    public void getAnswer(String homework, Callback someone) {
        if ("1+1=?".equals(homework)) {
            someone.doCallback(homework, "2");
        } else if("当x趋向于0,sin(x)/x =?".equals(homework)) {

            System.out.print("思考:");
            for(int i=1; i<=3; i++) {
                System.out.print(i+"秒 ");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println();
            someone.doCallback(homework, "1");
        } else {
            someone.doCallback(homework, "(空白)");
        }
    }
}

3、Client端

package com.callback;

public class Client implements Callback {

	@Override
	public void doCallback(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 Server service) {
		new Thread(new Runnable() {

			@Override
			public void run() {
				service.getAnswer(homework, Client.this);
			}
		}).start();

		goHome();
	}

	public void goHome() {
		System.out.println("我回家了……好室友,帮我写下作业。");
	}
}
4、测试

package com.callback;

public class CallbackTestMain {
	public static void main(String[] args) {
		Client student = new Client();
		String homework = "当x趋向于0,sin(x)/x =?";
		student.ask(homework, new Server());
	}
}