我有一个抽象的Catalog类,如下所示。它有一个静态方法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
}
...
}
首先,一般来说隐藏静态方法是否可以?我知道这是可能的,但它也似乎不应该经常做的事情。这也是一个有效的例子,可以隐藏静态方法,还是有更好的方法来做我想做的事情?
答案 0 :(得分: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*/};
}
}
答案 1 :(得分:1)
你并没有真正隐藏它,因为你总能做到
Catalog.OpenCatalog(...);
如果你想要基类版本。实际上,静态方法与特定类相关联,而不是虚拟的。您可以在派生类的基类中调用静态方法,这是一个很好的方便。
答案 2 :(得分:0)
我从未在“代码嗅觉”方面发现反对使用私有/内部静态方法的论据。
一个很好的实际示例可能是某种服务/实用程序库中的扩展方法,您只想在该库中扩展。
internal static ShippingRateType ToShippingRateType(this ProviderShippingRateType rateType) { }