2013-05-31 105 views
6

我發現,在C#中,你可以實現一個Singleton類,如下所示:實現單繼承類

class Singleton 
{ 

    private static Singleton _instance; 

    public static Singleton Instance 
    { 
     get { return _instance ?? (_instance = new Singleton()); } 
    } 

    protected Singleton() { } 
} 

這對於Singleton類型的實例工程,即:

var a = Singleton.Instance; 
var b = Singleton.Instance; 
Console.WriteLine(ReferenceEquals(a, b)); //Prints True. 

但什麼如果我想要Singleton的派生類也遵循Singleton模式,即:

class A:Singleton 
{ ... } 
A a = A.Instance; 

在這種情況下,通過Singleton類訪問靜態成員Instance,並創建一個Singleton實例,這不是目標。 此外,還有兩個主要問題,這個解決方案:

  • 派生類可以實現自己的構造和適度寬鬆的Singleton模式。
  • 如果存在的Singleton另一個實例,則派生類將要引用少派生的實例

我的問題是:有另一種方式來實現在C#中的Singleton類確保派生類也是單身?

+0

有趣的問題,我建議給這個讀:http://msmvps.com/blogs/jon_skeet/archive/2006/01/20/singleton-inheritance.aspx –

回答

17

忽略通常的「不要使用Singleton,看看你的設計。」參數,你可以想見,實現一個作爲正是如此(假設你的派生類有默認構造函數):

public abstract class Singleton<T> where T : class, new() 
{ 
    private static T _instance; 

    public static T GetInstance() 
    { 
     if(_instance == null) 
      _instance = new T(); 
     return _instance; 
    } 
} 

,並得出正是如此:

public class SingletonA : Singleton<SingletonA> { /* .... */ } 
public class SingletonB : Singleton<SingletonB> { /* .... */ } 

但是,我真的不親自提倡這種做法單。他們確實有他們(罕見)的用途,但他們可能會變得更加痛苦 - 轉向榮耀的全球可變容器。

此外,請注意線程安全。

+2

我也會謹慎使用實例屬性比GetInstance()方法。如果將鼠標懸停在調試器中的Instance屬性上,而由於代碼中構造的實例的副作用而導致斷點擊中,則會發生一些有趣的事情。當然,a)避免Singleton模式和b)避免構造函數中的副作用要好得多。 –

+0

@DanBryant,絕對正確 - 已編輯。 –

+0

+1「'不要使用Singleton,看看你的設計。」 –

3

我的問題是:是否有另一種方法來實現C#中的Singleton類,以確保派生類也是單例?

嗯,你可以有構造函數中某種檢查的是:

  • this實際類型密封
  • this的實際類型的Singleton
  • 直接子類
  • 沒有創建該類型的其他實例(保留HashSet<Type>

但是,這似乎毫無意義。你的基類實際上意味着什麼?

單例模式是easy to implement properly(順便說一句,你的例子沒有 - 它不是線程安全的),爲什麼有基類?基類本身不會是單例(可能會有很多實例 - 每個子類一個),所以有什麼好處?

在我看來,「我是一個單一的對象的實際類型」不是一個適當的基礎繼承的第一位,坦率地說,我會盡量避免單身模式儘可能無論如何。

如果你真的想要一個基類,它應該是因爲有一些共同的功能,所有的子類自然繼承。這不太可能與固有地相關,以處理這些子類是否是單身人士。