单例Swing组件

3

我正在开发一个swing应用程序,其中有一个工厂类,它考虑到单例模式提供组件。例如:

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的各种监听器。

这个模式有什么缺陷吗?我能否在两个同时可见的父组件中使用同一组件或监听器?

先感谢您。

2个回答

8
它存在一个主要缺陷:通过使每个组件全局可访问,它促进了封装的缺乏。这可能很快导致意大利面式代码,其中每个对象都使用任何其他对象,而不是具有提供封装方法的短依赖项列表。
另一个问题与实现有关:同步是不必要的,因为Swing组件不是线程安全的,只能从事件分派线程中使用。因此,您应该只有EDT调用您的方法,这使得同步是不必要的。
最后,组件只能有一个父组件。例如,如果同一组件必须在两个不同的框架中显示,则需要两个此组件的实例。

0
除了单例模式带来的耦合问题(即程序中许多类都依赖于工厂,如果工厂发生变化,系统的许多部分都会受到影响),您的单例工厂应该在多线程环境下工作。
但是要小心不要进行优化。有一种称为双重检查锁定的技术可用于优化您的解决方案以获得更高的并发度,但它具有非常微妙的问题。如果您感兴趣,请参见此声明(并注意签署它的人):http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html 为了消除对工厂的耦合,我更愿意在一些顶层类中创建共享结构(表、监听器、框架),这些类还会创建需要引用这些结构的对象,并将这些结构传递到它们的构造函数中。但这只是一个建议,我不知道程序的整体结构。

-1:Swing组件只能在单个线程中使用:EDT。而且OP的代码已经是线程安全的。使用双重检查锁定只会使它更加脆弱。 - JB Nizet
如果你真的读了答案,你会发现我告诉他要避免双重检查锁定。提示:“但要小心不要优化它”,“...,但它有非常微妙的问题”。而且没有什么可以阻止你从与EDT不同的线程修改Swing组件。请参见:http://java.sun.com/developer/technicalArticles/Threads/swing/ “如果您从事件分派线程以外的任何线程修改Swing组件数据,则必须采取预防措施以确保数据完整性。”我不明白为什么这个答案应该被踩,但无论如何... - joergl
这篇文章来自2001年,已经完全过时了。请阅读http://docs.oracle.com/javase/7/docs/api/javax/swing/package-summary.html#threading代替:*所有Swing组件和相关类(除非另有说明),必须在事件分派线程上访问*。 - JB Nizet
所以,这里有另一个链接来自http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html(API链接在那里,所以我猜它不过时):“一些Swing组件方法在API规范中被标记为“线程安全”;这些方法可以从任何线程安全地调用。” -> 没有普遍规则。 - joergl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接