在面向对象系统中,对象可以触发一组事件。Java 编程语言为定义基于观察者设计模式(Observer design pattern)的事件侦听器提供了支持,但当您需要使用以其他语言编写的对象时,这还不够。使用 Java Native Interface (JNI) 在本地事件源和 Java 侦听器之间进行通信,可能需要一些技巧,尤其是有多线程环境中。在本文中,我们描述了一种透明处理从本地代码到 JVM 的事件通信的设计模式。您可以使用这种设计来提供到遗留本地应用程序的 Java 接口,或者构建带 Java 侦听器的本地应用程序。
观察者设计模式
观察者设计模式定义了事件侦听器与事件创建者之间的多对一依赖关系。当事件创建者触发一个事件时,其所有侦听器接收到该事件的通知。由于事件创建者和侦听器是无关的,您可以单独使用或修改它们。这种设计模式是事件驱动编程的核心,被广泛用于 GUI 框架,比如 Swing 和 SWT。
如果整个应用程序都使用 Java 编程语言编写,实现观察者设计模式相当简单。图 1 中的类图给出了一个例子:
图 1. 观察者设计模式
Java 本地应用程序侦听器
不过,在某些情况下,我们想要让本地应用程序支持 Java 侦听器。大量应用程序(包括应用程序入口点)可能以本地代码编写,而应用程序以与其用户界面交互的方式生成事件。在这种情形下,支持基于 Java 用户界面的最佳方式是让 Java 类将自身注册为应用程序生成的各种事件的侦听器。简而言之,通过支持以 Java 语言编写的侦听器,可以获得支持 Java 的 本地应用程序。
图 2 所示的类图给出了一个示例场景。CEventSource 类用 C++ 语言编写。它使用 addMouseDownListener() 和 removeMouseDownListener() 让侦听器注册和取消注册其 “鼠标按下” 事件。它想要所有侦听器实现 IMouseDownListener 接口。
图 2. 示例场景的类图
注意,IMouseDownListener 是一个 C++ 抽象类。那么,Java 类如何注册事件才不会引入 Java 侦听器和 CEventSource 类之间的编译时绑定呢?在其注册事件后,CEventSource 类如何调用 Java 类中的方法呢?这正是 Java Invocation API 的用武之地。
Java Invocation API
Invocation API 让您可以将 JVM 加载到一个本地应用程序中,而不必显式地链接 JVM 源(请参阅 参考资料)。 通过在 jvm.dll 中调用一个函数,可以创建一个 JVM,jvm.dll 还将当前本地线程连接到 JVM。然后,您可以在 JVM 中从本地线程调用所有 Java 方法。
然而,Invocation API 无法彻底解决问题。您不希望 CEventSource 类具有与 Java 侦听器的编译时依赖关系。另外,Java 侦听器不应该承担使用 JNI 来注册带 CEventSource 的侦听器的责任。
代理设计模式
通过使用代理设计模式(Proxy design pattern),可以避免这一弊端。通常来说,代理是另一个对象的占位符。客户端对象可以处理代理对象,而代理封装了所有使用本地方法的细节。代理模式的细节显示在图 3 中:
图 3. 代理设计模式示例
EventSourceProxy 是 CEventSource 类的代理。要将其自身注册为一个侦听器,客户端应该实现 IJMouseDownListener 接口。该接口类似于 IMouseDownListener,但它是用 Java 代码编写的。当第一个客户端调用其 addMouseDownListener() 方法时,它使用 registerListener() 本地方法来将其自身注册为一个带 CEventSource 的侦听器。registerListener() 方法用 C++ 语言来实现。它创建一个 JMouseDownListener 对象,并将其注册为一个带 CEventSource 的侦听器。当 JMouseDownListener 的 onMouseDown 事件被触发时,JMouseDownListener 中的 onMouseDownListener() 方法使用 Invocation API 来通知 EventSourceProxy。
EventSourceProxy 还维持一组使用它来注册的侦听器。无论其 onMouseDown 何时被触发,它将通知该组中的所有侦听器。注意,即使针对该事件存在多个 Java 侦听器,只有代理的一个实例被注册为具有 CEventSource。代理将 onMouseDown 事件委托给它的所有侦听器。这防止了本地代码和 Java 代码之间不必要的上下文切换。
1
2
3
4
5
下一页>>