【发布时间】:2013-12-11 16:59:00
【问题描述】:
我对 OSGi 世界有些陌生。我仍然无法理解一些概念。
我正在尝试使用 Swing、Equinox 和声明式服务创建图形 OSGi 应用程序。目标是简化为应用程序创建插件和扩展的过程。
我偶然发现了一个设计问题,由于我是从头开始做这件事的,所以我想尽我所能使用所有最佳实践。
我确实有一个包含 API 的包,并且只公开要作为服务实现的接口。
public class SomeClass {
}
public interface Manager<T> {
void add(T obj);
void update(T obj);
void remove(T obj);
}
public interface SomeClassManager extends Manager<SomeClass> {
}
public interface Listener<T> {
void added(T obj);
void updated(T obj);
void removed(T obj);
}
public interface SomeClassListener extends Listener<SomeClass> {
}
假设我有一个包 (Core),它提供的服务是某些类型对象的管理器(它基本上包含一个内部列表并添加、删除和更新它)。
public class SomeClassCoreManager implements SomeClassManager {
private ArrayList<SomeClass> list = new ArrayList<SomeClass>();
private ArrayList<SomeListener> listeners = new ArrayList<SomeListener>();
protected void bindListener(SomeListener listener) {
listeners.add(listener);
}
protected void undindListener(SomeListener listener) {
listeners.remove(listener);
}
public void add(SomeClass obj) {
// Adds the object to the list
// Fires all the listeners with "added(obj)"
}
public void update(SomeClass obj) {
// Updates the object in the list.
// Fires all the listeners with "updated(obj)"
}
public void remove(SomeClass obj) {
// Removes the object from the list.
// Fires all the listeners with "removed(obj)"
}
}
我还有第二个包 (UI) 负责处理主 UI。它不应该“关心”管理自身的对象,而是应该在添加、删除或更改对象以更新 JTree 时通知它。为此,我使用了白板模式:UI 包实现了一个服务,核心包使用该服务来触发对象更改事件。
public class MainWindow extends JFrame {
private JTree tree = new JTree();
private SomeClassManager manager;
protected void activate() {
// Adds the tree and sets its model and creates the rest of the UI.
}
protected void bindManager(SomeClassManager manager) {
this.manager = manager;
}
protected unbindManager(SomeClassManager manager) {
this.manager = null;
}
}
public class SomeClassUIListener implements SomeClassListener {
public void added(SomeClass obj) {
// Should add the object to the JTree.
}
public void updated(SomeClass obj) {
// Should update the existing object in the JTree.
}
public void removed(SomeClass obj) {
// Should remove the existing object from the JTree.
}
}
我的问题如下:
MainWindow 是一个 DS 组件。我正在使用它的激活器来启动整个 UI。实例创建由 OSGi 处理。
为了从经理那里获得更新,我将 SomeClassUIListener 公开为声明式服务。它的实例也由 OSGi 处理。
我应该如何从 SomeClassUIListener 访问 JTree 模型的实例?
我想出了几个选项,但我不确定要使用哪个:
选项 1: 为 UI 包使用某种内部 DI 系统(如 Guice 或 Pico),并将其放入具有静态方法的类中,以获取它并在整个包中使用它。
这种方法似乎有些人不赞成。
选项 2: 通过 OSGi 在 SomeClassUIListener 中注入对 MainWindow 的引用(通过将其转换为服务)并从那里开始。这是可能的还是可取的?在我看来,这是更简单的解决方案。但是,另一方面,随着 UI 变得越来越复杂,组件配置文件不会使包变得混乱吗?
选项 3: 仅为侦听器创建单独的包并使用 OSGi 更新 MainWindow。这在我看来有点极端,因为随着 UI 复杂性的增加,我将不得不创建大量的捆绑包。
选项 4: 使用 MainWindow 类来实现监听器。但是,主 UI 包中的服务越多,MainWindow 类就越大。我认为这不是一个好的选择。
我想不出更多的选择。以上任何一条路都可以吗?还是有其他选择?
提前谢谢你。
编辑:
只是澄清一下,因为 Peter Kriens 对这个问题有一些疑问。
我的目标是将用户界面与管理器分离。 Manager 我的意思是一种存储库,我在其中存储某种类型的对象(例如,如果您考虑http://docs.oracle.com/javase/tutorial/uiswing/components/tree.html 上的 Oracle 的 JTree 教程,管理器将包含 Books 的实例)。
Manager 可以被任何其他捆绑包使用,但根据我目前的计划,它会通知在其中注册的任何侦听器。侦听器可以是主 UI 包,但也可以是选择侦听更新的任何其他包。
【问题讨论】:
-
Richard Hall 的 OSGi in Action 一书中有一个基于此模型的 GUI 程序作为示例。您可能还想查看felix.apache.org/site/…
-
我已经检查了你提到的例子。这本书的源代码确实可以回答我的问题!在第 11 章的paint-example-ds 中,windowlistener 提示了一个解决方案:我可以在将 SomeClassCoreManager 绑定到 MainWindow 时注册监听器。这样我就可以在监听器中注入我需要的任何组件。我提到的来源可能在link
标签: java swing osgi equinox declarative-services