或者实现Singleton

时间:2013-08-13 04:51:53

标签: java design-patterns

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

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 个答案:

答案 0 :(得分:10)

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

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

public enum Singleton {
    INSTANCE;

    // methods
}

来自Effective Java:

  

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

答案 1 :(得分:1)

为什么不使用枚举来实现Singleton?

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

虽然这两种解决方案都没有什么特别的错误,但Wikipedia的这个解决方案应该为您提供最佳的兼容性,并为您提供一个线程安全的单例:

  

马里兰大学计算机科学研究员Bill Pugh撰写了关于使用Java实现Singleton模式的代码问题。[11] Pugh对“双重检查锁定”习惯的努力导致了Java 5中Java内存模型的变化,以及通常被认为是在Java中实现Singletons的标准方法。被称为初始化按需持有者习惯用法的技术尽可能地懒惰,并且适用于所有已知版本的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;
        }
}