OSGi UI应用程序中的最佳实践

Jos*_*elo 5 java swing osgi declarative-services equinox

我对OSGi世界有些新意.还有一些概念让我望而却步.

我正在尝试使用Swing,Equinox和Declarative Services创建一个图形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> {
}
Run Code Online (Sandbox Code Playgroud)

假设我有一个bundle(Core),它提供的服务是某些类型对象的管理器(它基本上包含一个内部List并添加,删除和更新它).

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)"
      }

}
Run Code Online (Sandbox Code Playgroud)

我还有第二个包(UI)来处理主UI.它不应该"关心"管理自身的对象,但是在添加,删除或更改对象以更新JTree时应该通知它.为此,我使用了一个Whiteboard模式:UI包实现了一个服务,Core bundle使用该服务来触发对象更改事件.

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.
     }

}
Run Code Online (Sandbox Code Playgroud)

我的问题如下:

MainWindow是一个DS组件.我正在使用它的激活器来启动整个UI.实例创建由OSGi处理.

为了从管理器获取更新,我将SomeClassUIListener公开为声明式服务.它的实例也由OSGi处理.

我应该如何从SomeClassUIListener访问JTree模型的实例?

我提出了几个选项,但我不确定使用哪个:

选项1: 为UI包(如Guice或Pico)使用某种内部DI系统,并将其放在具有静态方法的类中以获取它并在整个包中使用它.

一些人似乎不赞成这种做法.

选项2: 通过OSGi在SomeClassUIListener中注入对MainWindow的引用(通过将其转换为服务)并从那里开始.这是可行的还是可取的?在我看来,这是更简单的解决方案.但是,另一方面,随着UI变得越来越复杂,这不会使组件配置文件变得混乱吗?

选项3: 仅为侦听器创建单独的包,并使用OSGi更新MainWindow.这在我看来有点极端,因为随着UI复杂性的增长,我将不得不创建大量的bundle.

选项4: 使用MainWindow类实现监听器.但是,主UI包中的服务越多,MainWindow类就越大.我认为这不是一个好选择.

我想不出更多选择.以上任何一种方式都可以吗?还是有其他选择吗?

先感谢您.

编辑:

只是为了澄清Peter Kriens对这个问题有些怀疑.

我的目标是将用户界面与Manager分离.通过管理器我的意思是一种存储库,我在其中存储某种类型的对象(例如,如果您在http://docs.oracle.com/javase/tutorial/uiswing/components/tree.html上考虑Oracle的JTree教程,经理将包含图书的实例).

管理员可以被任何其他捆绑使用,但根据我目前的计划,它会通知在其中注册的任何听众.侦听器可以是主UI包,但也可以是选择侦听更新的任何其他包.

Hen*_*sek 0

这里的一些选择是将树模型实例作为侦听器方法中的参数传递。

public void added(JTree tree, SomeClass obj)
Run Code Online (Sandbox Code Playgroud)

这样监听器管理器将只负责监听器逻辑,而不负责树状态。

另一个不错的选择是创建一个单独的TreeProviderService,负责JTree为应用程序保存和提供单例实例。在这种情况下,您将TreeProviderService直接从听众那里消费。