Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 交替实现单例_Java_Design Patterns - Fatal编程技术网

Java 交替实现单例

Java 交替实现单例,java,design-patterns,Java,Design Patterns,实现单例设计模式的标准方法如下: public class Singleton { private static Singleton instance = new Singleton(); public static Singleton getInstance() { return instance; } private Singleton() {} } 我想知道您是否也可以这样实现它: public class Singleton {

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

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

如果是,那么哪个版本更好?

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

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

马里兰大学计算机科学研究员比尔·普格(Bill Pugh)曾写过关于单例模式在Java中实现时的代码问题。[11]普格在“双重检查锁定”方面的努力这个习惯用法导致了Java5中Java内存模型的变化,以及通常被认为是Java中实现单例的标准方法的变化。这种被称为按需初始化持有者习惯用法的技术尽可能地懒惰,并且在所有已知的Java版本中都能工作。它利用了关于类初始化的语言保证,因此可以在所有符合Java的编译器和虚拟机中正常工作。 嵌套类的引用时间不早于调用getInstance()的时间(因此类加载器的加载时间也不早于此)。因此,该解决方案是线程安全的,不需要特殊的语言构造(即volatile或synchronized)


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

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

public enum Singleton {
    INSTANCE;

    // methods
}
来自有效Java:

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


为什么不使用enum实现单例呢

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

第一个也是一样。@Henry谢谢你指出它,我只是误读了代码。是的,它确实使用了封装。@denis.soloneko:谢谢!呵呵。那很酷。枚举值何时初始化?这是否解决了
SingletonHolder
技术解决的所有并发问题?@Jason C:初始化
enum
类时,非常像为
static
成员运行
static
初始值设定项时。对它解决了所有并发问题,同样,它基本上与
静态
初始值设定项相同。
私有
构造函数不会阻止可使用反射获取构造函数句柄的可信使用者实例化。可使用反射调用名为
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;
     }
 }