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_Singleton - Fatal编程技术网

Java 单例模式推荐方法

Java 单例模式推荐方法,java,design-patterns,singleton,Java,Design Patterns,Singleton,案例1: 案例2: public class Singleton { public static final Singleton INSTANCE = new Singleton(); private Singleton() { ... } } 第二种方法是实现Singleton设计模式的推荐方法吗,因为我在任何Singleton模式的示例中都没有见过第一种方法。创建Singleton的最佳方法是使用Enum public class Singleton { pr

案例1:

案例2:

public class Singleton {

  public static final Singleton INSTANCE = new Singleton();

  private Singleton() {
    ...
  }
}

第二种方法是实现Singleton设计模式的推荐方法吗,因为我在任何Singleton模式的示例中都没有见过第一种方法。

创建Singleton的最佳方法是使用Enum

public class Singleton {

  private static final Singleton INSTANCE = new Singleton();

  private Singleton() {
    ...
  }

  public static Singleton getInstance() {
    return INSTANCE;
  }
}

在不讨论单例作为反模式的所有内容的情况下(但您应该仔细阅读!),目前在Java中创建单例的最佳方法是使用枚举

public enum Foo {
    INSTANCE;
}
这样做更好的原因是JVM保证在任何时候都只存在一个枚举实例(每个类加载器)。它是线程安全的,并且不能使用反射来创建singleton的另一个实例


枚举值也是惰性实例化的,因此在第一次访问
singleton.INSTANCE
之前不会创建singleton。

是的,显然第二种方法是实现Sigleton模式的首选方法,在getInstance()内您必须检查实例是否已创建,然后返回相同的实例,并且只有在没有该类的实例时才创建新实例


还将getInstance方法设置为静态方法

在您的示例中,案例1更简单,因此更好。 但是想知道如果你的构造函数更复杂,有一些参数会发生什么。此时,你真的需要这样的东西:

public enum Singleton {
    INSTANCE;
}

创建Singleton对象的第一个过程甚至在使用Singleton类之前就创建了该类的实例,这不是最好的使用方法

在第二次实现中也存在同样的问题。 我首选的单例实例创建方式:

public class Singleton {

 private static final Singleton INSTANCE;

 private Singleton(string a, string b, string c) {
   ...
 }

public static Singleton getInstance(string a, string b, string c) {
   if (INSTANCE != null) { //note in multiple thread env, need add synchronize here.
       ......
   }
   return INSTANCE;
}
}
上述单线程实例创建的实现在单线程环境中是可以的,但在多线程环境中,两个线程可能同时访问if块,所以它们将具有不同的实例。这可以通过以下方式解决:

 private static final Singleton INSTANCE = null;
 public static Singleton getInstance(){
      if(INSTANCE == null)
        INSTANCE = new Singleton();
    return INSTANCE;
 }

希望这有帮助。

这是我如何用enum实现单例的

private static final Singleton INSTANCE = null;
 public static Singleton getInstance(){
    if(INSTANCE == null){
        synchronized (Singleton.class) {
            if(INSTANCE == null){
                INSTANCE = new Singleton();
            }
        }
    }
    return INSTANCE;
 }

我只是指静态的。没有真正的区别。getter对于延迟实例化可能很有用,但是您没有这样做(除了类加载器已经做的事情)。我认为懒惰和渴望仍然是唯一的区别。谢谢(除非还有一些我们忽略的差异)否:建议使用枚举方法,但如果应用程序受益于延迟加载,你还会推荐使用enum吗?你能详细解释一下为什么它比上述两种方法好吗?当对象实例化变得更复杂时,你还必须使用获取它的方法。您的示例很简单,因为它调用默认构造函数。设想一个场景,在这个场景中,您的单例对象必须通过工厂模式获取。是的,所以我建议您使用方法getInstance,而不是构造函数方式。当您使用工厂模式时,GetInstance将起作用。不知道枚举值是惰性实例化的。谢谢你的信息!
import static collections.concurrancy.ConcurrentHashMapInstanceEnum.STAFF;
public enum ConcurrentHashMapInstanceEnum {
    STAFF;
    private ConcurrentHashMap<Integer,Person> concurrentHashMap = null;

    private ConcurrentHashMapInstanceEnum() {
            concurrentHashMap = new ConcurrentHashMap(10, 5f, 4);
    }

    public ConcurrentHashMap getConcurrentHashMap() {
        return concurrentHashMap;
    }
}    
 staffList = STAFF.getConcurrentHashMap()