我正在阅读关于Singleton设计模式和评估不同的实现。我怀疑以下的实现:
:一种。使用静态内部类的单例实现
public class SingletonWithStaticClass {
private SingletonWithStaticClass(){}
private static class SingletonInnerClass{
public static SingletonWithStaticClass INSTANCE = new SingletonWithStaticClass();
}
public static SingletonWithStaticClass getInstance(){
return SingletonInnerClass.INSTANCE;
}
}
B中。单身双重检查锁定
public class SingletonWithDoubleCheck {
private static SingletonWithDoubleCheck INSTANCE = null;
private SingletonWithDoubleCheck(){
if(INSTANCE != null){
throw new RuntimeException("Accessing private constructor is prohibited. Use getInstance method instead");
}
}
public static SingletonWithDoubleCheck getInstance(){
if(INSTANCE == null){
synchronized (SingletonWithDoubleCheck.class) {
if(INSTANCE == null){
INSTANCE = new SingletonWithDoubleCheck();
}
}
}
return INSTANCE;
}
}
哪一个更好?
我觉得我们可以在第一个实现中使用Reflection访问私有构造函数,其中第二个实现是安全的(来自Reflection攻击)。
但是,我不打算在我的生产代码中使用任何这些,我将使用 枚举 。但是出于这两个,当考虑反射攻击时,是不是第一个实现被破坏?
如果我的理解错误,请纠正我。
答案 0 :(得分:6)
两者都过于复杂。第一个是Java 5.0之前的最佳选择,但第二个从来都不是一个好选择。它在Java 5.0之前没有用,它需要一个volatile
字段,在此版本之后你可以使用enum
我更喜欢使用enum
来定义一个只有一个实例的类。它是一个final
类,线程安全,延迟加载,并且有一个private
构造函数。
enum Singleon {
INSTANCE;
}
双锁定单例仅在必须在其构造中提供配置信息时才有用。在这种情况下,我更喜欢使用依赖注入来提供/配置单例,并且只有不需要配置的无状态单例。
答案 1 :(得分:1)
两者都不好 - 并且尝试使用不同的比例来比较它们会适得其反。
第一个是不必要的复杂,正如你所说的那样,反思黑客是开放的,但另一个也是如此,只是略微不那么明显。
第二个使用synchronized
并附带费用。