【发布时间】:2016-04-03 10:28:25
【问题描述】:
我正在阅读单例设计模式并评估不同的实现。我对以下实现有疑问:
A.带有静态内部类的单例实现
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;
}
}
哪个更好?
我觉得我们可以在第一个实现中使用反射访问私有构造函数,而第二个实现是安全的(来自反射攻击)。
但是,我不会在我的生产代码中使用这些,而是使用 enum。但是在这两个中,当考虑反射攻击时,不是第一个实现被破坏了吗?
如果我的理解有误,请纠正我。
【问题讨论】:
-
单例设计模式通常不是为了承受某种蓄意的“攻击”。如果有人使用反射来公开私有构造函数,则他们有责任知道他们所做的事情是否违反了代码的预期用途。
-
第二个是不安全的,如已发布。这已经被散列和重新散列。我完全同意凯尔伍德。单例是一种设计(反)模式。不是安全工具。如果有人可以访问您的代码,他可以使用反射做任何事情。
-
@JBNizet AFAIK 如果您使用
volatile字段,它已在 Java 5.0 中修复,但它表明它容易出错。 -
考虑在 99% 的情况下避免使用单例:stackoverflow.com/questions/137975/…
-
@PeterLawrey 是的,具有易失性。但正如发布的那样,它是不安全的。事实上,它很容易搞砸,应该避免,尤其是当有更好的选择时。一般来说,应该避免使用单例。
标签: java design-patterns singleton