【问题标题】:Is it ok to hide a static method?隐藏静态方法可以吗?
【发布时间】:2010-08-18 22:52:52
【问题描述】:

我有一个抽象的目录类,如下所示。它有一个静态方法 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          
    }

    ...

}

首先一般可以隐藏静态方法吗?我知道这是可能的,但它似乎也是不应该经常做的事情。这也是一个可以隐藏静态方法的有效示例,还是有更好的方法来做我想做的事情?

【问题讨论】:

    标签: c# .net class-design static-methods


    【解决方案1】:

    您似乎正试图以一种非常尴尬的方式创建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*/};
      }
    
    }
    

    【讨论】:

    • 好的,我明白了。虽然我不会总是直接调用每个具体目录类型的构造函数。例如,当我的 FileSystemCatalog 打开时,它会通过 DataContractSerializer 从 XML 文件中反序列化。调用构造函数的确实是 DataContractSerializer。所以我需要一个静态方法,我可以在某个地方实例化 aDataContractSerializer 并使用它来尝试从文件中反序列化目录。
    • 是的,没关系,我只是为了说明而输入了new FileSystemCatalog。另外,这个方法不是在Catalog以外的类中,该方法不需要是静态的,因此可以在单元测试中模拟。
    【解决方案2】:

    你并没有真正隐藏它,因为你总是可以做到的

    Catalog.OpenCatalog(...);
    

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

    【讨论】:

      【解决方案3】:

      就“代码异味”而言,我从未发现反对使用私有/内部静态方法的论据。

      一个很好的实际示例可能是某种服务/实用程序库中的扩展方法,您只想在该库中扩展。

      internal static ShippingRateType ToShippingRateType(this ProviderShippingRateType rateType) { }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-26
        • 2012-11-07
        • 1970-01-01
        • 2014-10-08
        • 1970-01-01
        相关资源
        最近更新 更多