Компонент Singleton Swing

Я разрабатываю свинг-приложение, где у меня есть класс Factory, который предоставляет компонент с учетом Singleton. Нравиться:

public final class ComponentFactory {
    private static LibraryFrame libraryFrame;
    private static LibraryTableScrollPane libraryTableScrollPane;

    public static synchronized LibraryFrame getLibraryFrame() {
        if (libraryFrame == null) {
            libraryFrame = new LibraryFrame();
        }
        return libraryFrame;
    }

    public static synchronized LibraryTableScrollPane getLibraryTableScrollPane() {     
        if(libraryTableScrollPane == null) {
            libraryTableScrollPane = new LibraryTableScrollPane(getLibraryTable());
        }       
        return libraryTableScrollPane;
    }
}

Я использую этот компонент как:

add(ComponentFactory.getLibraryTableScrollPane())

Также я создаю класс ListenerFactory, который предоставляет различные слушатели Swing/AWT.

Есть ли у этой модели недостатки? Могу ли я использовать один и тот же компонент или прослушиватель с двумя одновременно видимыми родительскими компонентами?

Заранее спасибо.


person Tapas Bose    schedule 19.02.2012    source источник


Ответы (2)


У него есть серьезный недостаток: он способствует отсутствию инкапсуляции, делая каждый компонент доступным по всему миру. Это может очень быстро привести к спагетти-коду, в котором каждый объект использует любой другой объект вместо короткого списка зависимостей, предоставляющих инкапсулированные методы.

Другая проблема связана с реализацией: синхронизация не нужна, поскольку компоненты Swing не являются потокобезопасными и могут использоваться только из потока диспетчеризации событий. Таким образом, вы должны иметь только EDT, вызывающий ваши методы, что делает ненужной синхронизацию.

Наконец, компонент может иметь только один родительский компонент. Например, если один и тот же компонент должен отображаться в двух разных фреймах, вам понадобятся два экземпляра этого компонента.

person JB Nizet    schedule 19.02.2012

Помимо проблем с соединением, которые возникают с шаблоном singleton (= многие классы в вашей программе зависят от вашей фабрики -> если ваша фабрика изменится, это повлияет на многие части вашей системы.), ваша singleton factory должна работать в мульти- висячий контекст.

Но будьте осторожны, чтобы не оптимизировать его. Существует техника, называемая блокировкой с двойной проверкой, которая использовалась для оптимизации вашего решения для достижения более высокой степени параллелизма, но у нее есть очень тонкие проблемы. Если вам интересно, посмотрите это заявление (и обратите внимание на людей, подписавших его): http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Чтобы избавиться от привязки к вашей фабрике, я бы предпочел создать общие структуры (таблицы, прослушиватели, фреймы) в некоторых классах верхнего уровня, которые также создают объекты, которым нужны ссылки на эти структуры, и передают структуры в их конструкторы. Но это всего лишь совет, я не знаю общей структуры программы.

person joergl    schedule 19.02.2012
comment
-1: Компоненты Swing можно использовать только в одном потоке: EDT. И код OP уже потокобезопасен. Использование блокировки с двойной проверкой только сделает ее более хрупкой. - person JB Nizet; 19.02.2012
comment
Если вы действительно читаете ответ, вы видите, что я сказал ему избегать блокировки с двойной проверкой. Подсказка: но будьте осторожны, чтобы не оптимизировать его, ..., но у него есть очень тонкие проблемы. И ничто не мешает вам модифицировать компоненты Swing из потока, отличного от EDT. См.: java.sun.com/developer/technicalArticles/Threads/swing. Если вы изменяете данные компонента Swing из любого потока, кроме потока диспетчеризации событий, вы должны принять меры предосторожности для обеспечения целостности данных. Я не понимаю, почему ответ заслуживает отрицательного голоса, но что бы там ни было... - person joergl; 19.02.2012
comment
Эта статья от 2001 года и полностью устарела. Прочтите docs.oracle.com/javase Вместо этого /7/docs/api/javax/swing/: Все компоненты Swing и связанные с ними классы, если не указано иное, должны быть доступны в потоке диспетчеризации событий - person JB Nizet; 19.02.2012
comment
Итак, вот еще одна ссылка из docs.oracle.com/javase/tutorial/ uiswing/concurrency/ (там ссылки на API, поэтому я думаю, что он не устарел): некоторые методы компонентов Swing помечены как потокобезопасные в спецификации API; их можно безопасно вызывать из любого потока. -› Нет общего правила. - person joergl; 19.02.2012