2015-02-06 166 views
0

所以我有一個類A.它定義了很多的行爲(方法),但也留下很多的子類來實現。這個類永遠不會有一個實例。這只是要定義所有子類通用的行爲。 要擴展A的子類(A1,A2,A3等)都將是單例。我不希望這些子類有多個實例。從抽象類繼承的靜態類?

那麼明顯的方式做這將是創建一個抽象類A,然後靜態類A1,A2,A3,擴展A.

但很顯然,這不是在C#中允許的。我假設有一個很好的理由。微軟的人可能比我更瞭解更多關於面向對象的軟件設計。 但我只是需要一些幫助,找出爲什麼這個設計是「窮」,什麼會是一個替代更好的設計。


我正在寫使用WCF一個RESTful API。有一堆數據庫表,這個服務將在其上執行CRUD操作。有很多代碼對於所有表格都是通用的,並且很多代碼將會針對每個表格。而且,在任何給定時間只能在桌子上執行一個操作。

所以我想我可以有一個抽象類TableHandler。然後它的多個擴展如TableAHandler,TableBHandler等。因爲我只想要這些子類的一個實例,所以我想讓它們成爲靜態的。

+4

這是不允許的,因爲繼承是關於創建相關的對象類,而且你根本沒有用靜態類創建任何對象。告訴我們你想要解決什麼現實世界的問題,我們會看看我們是否可以提出解決方案。 – 2015-02-06 21:38:38

+0

@RobertHarvey我添加了一些關於我試圖解決的問題的信息。謝謝。 – AyushISM 2015-02-06 21:55:07

+0

使用[工廠方法](http://en.wikipedia.org/wiki/Factory_method_pattern)模式。如果你喜歡,使工廠方法單例服務的對象。 – 2015-02-06 21:55:53

回答

2

創建一個擴展您的基的普通類,但遵循具有私有構造函數和靜態訪問器的單例模式到實例。

abstract class A { } 

class A1 : A 
{ 
    private static A1 instance; 
    public static A1 Instance 
    { 
     get 
     { 
      if(instance == null) 
       instance = new A1(); 
      return instance; 
     } 
    } 

    private A1() { } 
} 

正如@ScottChamberlain指出,此實現不是線程安全的。使用靜態構造函數將使初始化線程安全。在這個問題中可以找到更多信息:Is the C# static constructor thread safe?

+1

是的,基本上這個問題並不需要不可能的靜態類,因爲通常如何設置單例模式(如此答案所示) – ryanyuyu 2015-02-06 21:42:10

+0

這不是一個非常安全的單例模式。如果多個線程在初始化階段同時調用屬性,則可能會存在多個'A1'副本。靜態方法和屬性應始終設法保證線程安全。 – 2015-02-06 22:19:57

2

繼承是影響對象的東西。根據定義,靜態類不允許實例化。因此,他們不能參與繼承。

實際上,靜態方法不能是虛擬的,這幾乎消除了能夠聲明繼承的靜態類的任何可能的用處。定義Singleton模式

0

簡單的方法是Lazy<T>

public abstract class A { } 

public class B : A 
{ 
    private static Lazy<B> _instance = new Lazy<B>(() => new B()); 

    private B() { } 

    public static B Instance 
    { 
     get 
     { 
      return _instance.Value; 
     } 
    } 
} 

這也將提供線程安全,創造你的單身人士。