2011-08-19 102 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; 
} 

此方法是線程安全的,因爲你只是在該方法返回的實例。