2011-08-19 69 views
1

任何人都可以识别此代码实现Singleton设计模式的Java/C#代码中的问题。实现Singleton设计模式[请建议]

有人能找到我在这个片段的执行缺陷吗?

class Singleton{ 
public static Singleton Instance() { 
if (_instance == null) 
_instance = new Singleton(); 
return _instance; 
} 
protected Singleton() {} 
private static Singleton _instance = null; 
} 
+1

出于兴趣,这是功课吗? –

+0

其实面试官问我这个问题.... – user40587

+0

如果是面试问题,我们可以说这个代码**没有**有任何**错误**。然后继续指出它是**不是线程安全的**,并使构造函数私有更安全。 – Samuel

回答

0

如果你是在多线程环境两个不同的线程可能进入if块,然后他们都将创建一个新的实例。添加锁定:

class Singleton{ 
    public static Singleton Instance() { 
     if (_instance == null) { 
      lock(typeof(Singleton)) { 
       if (_instance == null) { 
        _instance = new Singleton(); 
       } 
      } 
     } 
     return _instance; 
    } 
    protected Singleton() {} 
    private static Singleton _instance = null; 
} 
3

至于基伦说,它不是线程安全的...和你允许类从它派生,这意味着它不是一个真正的单身:

public class SingletonBasher : Singleton 
{ 
} 

Singleton x = Singleton.Instance(); 
Singleton y = new SingletonBasher(); 

它应该是无效的xy是不同的引用,它们都是非空 - 它违反了单例的概念。

(是的,我建议你my article on singleton implementations太:)

+0

我还可以使用class.forName.newInstance()创建多个实例,在java中有反射 –

2

实现单(约书亚Bloch的Effective Java的一个更好的办法)是使用枚举:如果您坚持用

enum Singleton { 
    INSTANCE(); 
    private Singleton() { 
     .... 
    } 
} 

您方法,你需要做三件事更多:

  • 使构造私有的(乔恩斯基特的建议)
  • 让_instance挥发性
  • 双锁的实例()
+0

还有没有完美的单身人士。有可以创建另一个实例的序列化技术如SOAP。 –

0

以上所有的答案是正确的。

在单例设计模式中,您不应该允许其他人为单例类创建实例。你必须拥有自己的权利。另一个实例可以请求你单身人士的实例。所以构造函数应该/必须是私有的。

在您的示例中,您将其设为受保护的,在这种情况下,如果您扩展单例类,则可以从其他实例创建实例。这种可能性不应该提供。

使构造函数在您的代码片段中是私有的,然后是它的单例类。

0

它不是线程安全的。

您可以用预先初始化以不同的方式实现:

private static Singleton _instance = new Singleton(); 

public static Singleton Instance() 
{ 
    return _instance; 
} 

此方法是线程安全的,因为你只是在该方法返回的实例。