Я немного новичок в мире OSGi. И некоторые концепции все еще ускользают от меня.Лучшая практика в приложении OSGi UI
Я пытаюсь создать графическое приложение OSGi с использованием Swing, Equinox и Declarative Services. Цель состоит в том, чтобы облегчить создание плагинов и расширений для приложения.
Я столкнулся с проблемой дизайна, и, поскольку я делаю это с нуля, я хочу использовать все лучшие практики, которые я могу.
У меня есть пакет, содержащий 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), который заботится о главном пользовательском интерфейсе. Он не должен «заботиться» о том, чтобы объект сам управлял, но должен быть уведомлен о добавлении, удалении или изменении объекта для обновления JTree. Для этого я использовал шаблон Whiteboard: пакет UI реализует службу, которая используется пакетом Core для запуска событий изменения объекта.
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. Я использую его активатор, чтобы инициировать весь пользовательский интерфейс. Создание экземпляра обрабатывается OSGi.
Чтобы получить обновления от менеджера, я подвергаю SomeClassUIListener как декларативную услугу. Его экземпляр также обрабатывается OSGi.
Как получить доступ к экземпляру модели JTree у SomeClassUIListener?
Я придумал несколько вариантов, но я не уверен, какой из них использовать:
Вариант 1: Используйте какой-то внутренней системы DI для расслоения UI (например Guice или Пико) и поставить он в классе со статическим методом, чтобы получить его и использовать его по всему набору.
Этот подход, по-видимому, не одобряется некоторыми.
Вариант 2: Вводите ссылку на MainWindow (путем превращения его в эксплуатацию) в SomeClassUIListener через OSGi и идти оттуда. Возможно ли это или целесообразно? Мне кажется, что это более простое решение. Но, с другой стороны, разве это не помешало бы пакету с файлами конфигурации компонентов, так как интерфейс стал все более сложным?
Вариант 3: Создайте отдельный комплект только для слушателей и используйте OSGi для обновления MainWindow. Это кажется мне немного экстремальным, так как мне придется создавать огромное количество пакетов, поскольку сложность пользовательского интерфейса возрастает.
Вариант 4: Используйте класс MainWindow для реализации прослушивателя. Но чем больше услуг в пакете основного UI, тем больше будет класс MainWindow. Я думаю, это не будет хорошим вариантом.
Я не могу придумать больше вариантов. Есть ли какие-либо из вышеперечисленных способов? Или есть другой вариант?
Заранее спасибо.
Edit:
Просто чтобы прояснить, как Питер Крайенс были некоторые сомнения по поводу этого вопроса.
Моя цель - отделить пользовательский интерфейс от Менеджера. К Менеджер Я имею в виду репозиторий, в котором я храню определенный тип объектов (например, если вы рассматриваете учебник JTree от Oracle по адресу http://docs.oracle.com/javase/tutorial/uiswing/components/tree.html, менеджер будет содержать экземпляры книг).
Менеджер может использоваться любым другим пакетом, но, согласно моему текущему плану, он уведомит зарегистрированного в нем слушателя. Слушателем может быть основной пакет пользовательского интерфейса, но также может быть любым другим пакетом, который хочет слушать обновления.
В OSGi в книге действий от Ричарда Холла есть программа GUI в качестве примера, основанного на этой модели. Вы также можете посмотреть http://felix.apache.org/site/apache-felix-application-demonstration.html –
Я проверил приведенные вами примеры. В исходном коде книги есть что-то, что может ответить на мой вопрос! В главе 11, в примере paint-example-ds, windowlistener намекает на решение: я мог зарегистрировать слушателя при привязке SomeClassCoreManager к MainWindow. таким образом я могу впрыскивать любые компоненты, которые мне нужны в слушателе. Источники, о которых я упоминал, можно найти в [link] (https://code.google.com/p/osgi-in-action/) –