2010-08-18 94 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(...); 

如果你想在基类版本。事实上,静态方法与特定的类相关联,并且不是虚拟的。这只是一个很好的方便,您可以调用派生类中的基类中定义的静态方法。