7

实现单例设计模式的标准方法是这样的:

public class Singleton {
    private static Singleton instance = new Singleton();

    public static Singleton getInstance() {
        return instance;
    }

    private Singleton() {}
}

我想知道你是否也可以像这样实现它:

public class Singleton {
    private Singleton() {}
    public final static Singleton INSTANCE = new Singleton();
}

如果是,哪个版本更好?

4

4 回答 4

10

两者都不。在这两种情况下,受信任的消费者都可以通过反射调用私有构造函数。另一个问题是,除非您采取额外的步骤来实现,否则这些实现不能很好地与序列化配合使用(默认情况下,如果您采用幼稚的方法,每次Singleton反序列化 a 时,它都会创建一个新实例)。

正确的解决方案是使用enum定义单个值的 。

public enum Singleton {
    INSTANCE;

    // methods
}

从有效的Java:

虽然这种方法尚未被广泛采用,但单元素枚举类型是实现单例的最佳方式。

于 2013-08-13T04:58:00.327 回答
1

为什么你不使用枚举来实现单例?

 public enum SingletonEnum {
     Instance;
     private static String testStr = "";

     public static void setTestStr(String newTestStr) {
         testStr = newTestStr;
     }

     public static String getTestStr() {
         return testStr;
     }

     public static String sayHello(String name) {
         return "Hello " + name;
     }
 }
于 2013-08-13T04:59:40.690 回答
0

在我看来,第一个更好,因为它看起来更符合面向对象的方法。

于 2013-08-13T04:56:27.980 回答
0

虽然这两种解决方案都没有什么特别的问题,但维基百科的这个解决方案应该给你最好的兼容性,并给你一个线程安全的单例:

马里兰大学计算机科学研究员 Bill Pugh 撰写了有关在 Java 中实现单例模式时的代码问题。 [11] Pugh 在“双重检查锁定”习语上的努力导致了 Java 5 中 Java 内存模型的变化,以及通常被认为是在 Java 中实现 Singleton 的标准方法。被称为按需初始化持有者习惯用法的技术尽可能地懒惰,并且适用于所有已知的 Java 版本。它利用了关于类初始化的语言保证,因此可以在所有符合 Java 的编译器和虚拟机中正常工作。嵌套类的引用不早于调用 getInstance() 的那一刻(因此类加载器不早于加载)。因此,

public class Singleton {
        // Private constructor prevents instantiation from other classes
        private Singleton() { }

        /**
        * SingletonHolder is loaded on the first execution of Singleton.getInstance() 
        * or the first access to SingletonHolder.INSTANCE, not before.
        */
        private static class SingletonHolder { 
                public static final Singleton INSTANCE = new Singleton();
        }

        public static Singleton getInstance() {
                return SingletonHolder.INSTANCE;
        }
}
于 2013-08-13T04:57:14.157 回答