Java 利用接口实现回调
2013-06-04 14:58
405 查看
在 Java 支持方法指针之前,Java 接口不能提供一种实现回调的好方法。如果您习惯于传递在事件驱动编程模型中调用的函数指针,则您会喜欢本技巧。
熟悉 MS-Windows 和 X Window System 事件驱动编程模型的开发人员,习惯于传递在某种事件发生时调用(即“回调”)的函数指针。Java 的面向对象模型目前并不支持方法指针,这样似乎就不可能使用这种很好的机制。但我们并不是一点办法都没有!
Java 的接口支持提供了一种获得回调的等价功能的机制。其技巧就是:定义一个简单接口,并在该接口中声明我们要调用的方法。
例如,假定我们希望在某个事件发生时得到通知。我们可以定义一个接口:
这使得我们可以控制实现该接口的类的任何对象。因此,我们不必关心任何外部类型信息。与在将 C++ 代码用于 Motif 时使用窗口小部件的数据域来容纳对象指针的难以控制的 C 函数相比,这种方法要好得多。
发出事件信号的类必须等待实现了 InterestingEvent 接口的对象,并在适当时候调用 interestingEvent() 方法。
在上例中,我使用 somethingHappened 谓词来跟踪是否应触发事件。在许多情况下,调用此方法足以保证向 interestingEvent() 发出信号。
希望接收事件通知的代码必须实现 InterestingEvent 接口,并将自身引用传递给事件通知程序。
下面给出上述例子的完整实现:
下面给出回调的模型和另一个实例以便我们更好的学习
熟悉 MS-Windows 和 X Window System 事件驱动编程模型的开发人员,习惯于传递在某种事件发生时调用(即“回调”)的函数指针。Java 的面向对象模型目前并不支持方法指针,这样似乎就不可能使用这种很好的机制。但我们并不是一点办法都没有!
Java 的接口支持提供了一种获得回调的等价功能的机制。其技巧就是:定义一个简单接口,并在该接口中声明我们要调用的方法。
例如,假定我们希望在某个事件发生时得到通知。我们可以定义一个接口:
public interface InterestingEvent{ // 这仅是一个常规方法。因此如果需要, // 它可有返回值,也可接收参数。 public void interestingEvent (); }
这使得我们可以控制实现该接口的类的任何对象。因此,我们不必关心任何外部类型信息。与在将 C++ 代码用于 Motif 时使用窗口小部件的数据域来容纳对象指针的难以控制的 C 函数相比,这种方法要好得多。
发出事件信号的类必须等待实现了 InterestingEvent 接口的对象,并在适当时候调用 interestingEvent() 方法。
public class EventNotifier{ private InterestingEvent ie; private boolean somethingHappened; public EventNotifier (InterestingEvent event){ // 保存事件对象以备后用。 ie = event; // 还没有要报告的事件。 somethingHappened = false; } //... public void doWork (){ // 检查在别处设置的谓词。 if (somethingHappened){ // 通过调用接口的这个方法发出事件信号。 ie.interestingEvent (); } //... } // ... }
在上例中,我使用 somethingHappened 谓词来跟踪是否应触发事件。在许多情况下,调用此方法足以保证向 interestingEvent() 发出信号。
希望接收事件通知的代码必须实现 InterestingEvent 接口,并将自身引用传递给事件通知程序。
public class CallMe implements InterestingEvent{ private EventNotifier en; public CallMe (){ // 创建事件通知程序,并将自身引用传递给它。 en = new EventNotifier (this); } // 为事件定义实际的处理程序。 public void interestingEvent (){ // 噢!必定发生了感兴趣的事件! // 执行某些操作 ... } //... }
下面给出上述例子的完整实现:
/* * 考虑这样一个应用:希望在某个事件发生时得到通知 */ interface InterestingEvent { public void interestingEvent(); } class EventNotifier { private InterestingEvent ie; //写成private List<InterestingEvent> eventList可以监听多个事件 private boolean somethingHappened; public EventNotifier(InterestingEvent ie) { this.ie = ie; this.somethingHappened = false; } public void setHappened() { this.somethingHappened = true; } public void doWork() { if (somethingHappened) { ie.interestingEvent(); } } } class ButtonPressedEvent implements InterestingEvent { @SuppressWarnings("unused") private EventNotifier en; public ButtonPressedEvent() { en = new EventNotifier(this); } public void interestingEvent() { System.out.println("button pressed "); } } class EventNotifierTest { public static void test() { //这里有两种调用方法。其中第二种采用匿名内部类,其原理跟上面“改变Client名字”是一样的 EventNotifier en = new EventNotifier(new ButtonPressedEvent()); en.setHappened(); en.doWork(); EventNotifier en2 = new EventNotifier(new InterestingEvent(){ public void interestingEvent() { System.out.println("inputtext change "); } }); en2.setHappened(); en2.doWork(); } } //这个类是用来测试的 public class JavaInterfaceCallBack { public static void main(String[] args) { ChangeNameTest.test(); EventNotifierTest.test(); } }
下面给出回调的模型和另一个实例以便我们更好的学习
/* * Java里面的接口回调,最简单的情况示意如下 */ interface A {} class B implements A {} class C implements A {} class Test { A b = new B(); A c = new C(); }
/* * 考虑这样一个应用: NameChanger动态地改变Client的名字 * 那NameChanger的changeName方法就要接收一个Client对象,然后获取(调用)Client的名字并作不同的处理 * Client也要持有NameChanger,因为要打印改变后的名字 */ class Client { private INameChanger changer; private String clientName; public Client(INameChanger changer) { this.changer = changer; } public void showMyNewName() { String newName = changer.changeName(Client.this); System.out.println(newName); } public String getName() { return clientName; } public void setName(String clientName) { this.clientName = clientName; } } interface INameChanger { public String changeName(Client client); } public class ChangeNameTest { public static void main(String[] args) { Client client = new Client(new INameChanger(){ public String changeName(Client client) { return "Mr." + client.getName(); } }); client.setName("Tom"); client.showMyNewName(); Client client2 = new Client(new INameChanger(){ public String changeName(Client client) { return "Miss." + client.getName(); } }); client2.setName("Lucy"); client2.showMyNewName(); } }
相关文章推荐
- Java利用接口实现回调
- Java 利用接口实现回调
- 利用java的接口实现回调
- Java学习笔记——利用接口和observer实现对象监视
- java程序利用接口实现发短信功能
- 需求:iOS自定义protocol与delegate来实现类似java的接口回调功能
- 利用 ICallbackEventHandler接口 实现客户端回调
- Android开发之图片处理专题(二):利用AsyncTask和回调接口实现图片的异步加载和压缩
- JAVA 利用XML生成json完成接口对接实现
- 利用回调实现Java的异步调用
- 利用自定义ClassLoader和接口逻辑后台可刷新缓存实现java-web项目的动态发布
- 利用接口回调实现Fragment之间的跳转
- 利用HttpClient实现接口-Java工具类(三)
- android中利用java.lang.reflect.Proxy实现私有接口
- 利用回调接口实现activity之前传数据
- java——通过Callable接口实现可回调参数的多线程
- 利用JAVA Comparator接口实现数组排序
- Java利用listener实现回调,即观察者模式
- 利用聚合接口实现Java查询身份证
- Java按时间梯度实现异步回调接口的方法