2010-08-18 265 views
3

我有一個抽象的目錄類如下。它有一個靜態方法OpenCatalog(),用於根據提供的位置類型返回特定的具體目錄。一旦確定了目錄類型,它就會調用正確的具體目錄類型的特定OpenCatalog()方法。例如,我可能有一個存儲在SQL數據庫中的Catalog的實現,或者存儲在文件系統中的另一個。請參閱下面的代碼。可以隱藏靜態方法嗎?

public abstract class Catalog 
{ 
    public static ICatalog OpenCatalog(string location, bool openReadOnly) 
    { 

     if(location is filePath) 
     { 
      return FileSystemCatalog.OpenCatalog(string location, bool openReadOnly); 
     } 
     else if(location is SQL server) 
     { 
      return SqlCatalog.OpenCatalog(string location, bool openReadOnly); 
     } 
     else 
     { 
      throw new ArgumentException("Unknown catalog type","location"); 
     } 
    } 

    ... 

} 

public abstract class FileSystemCatalog:Catalog 
{ 

    public static new ICatalog OpenCatalog(string location, bool openReadOnly) 
    { 
     //Deserializes and returns a catalog from the file system at the specified location 
    } 

    ... 

} 



public abstract class SqlCatalog:Catalog 
{ 

    public static new ICatalog OpenCatalog(string location, bool openReadOnly) 
    { 
     //creates an returns an instances of a SqlCatalog linked to a database 
     //at the provided location   
    } 

    ... 

} 

首先,一般情況下可以隱藏靜態方法嗎?我知道這是可以做到的,但它也只是一種人們不應該經常做的事情。這也是一個有效的例子,可以隱藏一個靜態方法,或者有更好的方法來做我想做的事情嗎?

回答

2

它看起來像你試圖以非常尷尬的方式創建abstract factory。實際發生的情況是,您違反了Single Responsibility Principle並將目錄創建問題與目錄問題混合在一起。你需要做的是使非靜態類CatalogFactory。這可以讓您隨時隨地獲得靈活性(例如依賴注入)。

public class CatalogFactory { 
    public ICatalog CreateCatalog(string location, bool openReadOnly) 
    { 

    if(location is filePath) 
    { 
     return OpenFileCatalog(string location, bool openReadOnly); 
    } 
    else if(location is SQL server) 
    { 
     return OpenSqlCatalog(string location, bool openReadOnly); 
    } 
    else 
    { 
     throw new ArgumentException("Unknown catalog type","location"); 
    } 
    } 
    FileSystemCatalog OpenFileCatalog(string location, bool openReadOnly) { 
    return new FileSystemCatalog{/*init*/}; 
    } 
    SqlCatalog OpenSqlCatalog(string location, bool openReadOnly) { 
    return new SqlCatalog{/*init*/}; 
    } 

} 
+0

好吧,我明白了。雖然我不會總是直接調用每個具體目錄類型的構造函數。例如,當我的FileSystemCatalog打開時,它通過DataContractSerializer從XML文件反序列化。它確實是調用構造函數的DataContractSerializer。所以我需要一個靜態方法,在那裏我可以實例化一個DataContractSerializer並使用它來試圖從一個文件反序列化一個Catalog。 – 2010-08-19 01:41:38

+0

是的,沒關係,我只是爲了說明而放入'新的FileSystemCatalog'。另外,並不是說這個方法在'Catalog'以外的類中,該方法不需要是靜態的,因此它可以在單元測試中被模擬。 – 2010-08-19 04:07:44

0

我從來沒有發現反對在「代碼味道」方面使用私有/內部靜態方法的爭論。

一個很好的實際例子可能是某種服務/實用程序庫內的擴展方法,您只想在該庫中進行擴展。

internal static ShippingRateType ToShippingRateType(this ProviderShippingRateType rateType) { } 
0

你是不是真的隱藏它,因爲你總是可以做

Catalog.OpenCatalog(...); 

如果你想在基類版本。事實上,靜態方法與特定的類相關聯,並且不是虛擬的。這只是一個很好的方便,您可以調用派生類中的基類中定義的靜態方法。

相關問題