2

我有一个泛型类,我们称之为它MyClass<T>,它需要有一个工厂方法,以便从客户端代码中抽象出构造函数的细节。

这两个选项哪个是正确的?(包括示例实例化代码)

  1. 原始泛型上的静态非泛型工厂方法: MyClass<T>

    MyClass<SomeType> instance = MyClass<SomeType>.CreateNew();
    
  2. 专用的非泛型静态实现上的静态泛型工厂方法:MyClass

    MyClass<SomeType> instance = MyClass.CreateNew<SomeType>();
    
4

2 回答 2

1

乍一看,您的问题的正确答案似乎是#1。这是因为您的课程是特定的MyClass<T>,因此工厂也应该是T特定的。但不仅仅是这个简单的答案。

在继续之前,我要添加第三种可能性:非静态工厂类。依赖于工厂的对象将具有一个公共属性,通过该属性它接收工厂对象。如果没有分配其他实例,则该属性的 Getter 将实例化默认工厂。这允许以后进行依赖注入,并且还有助于编写依赖于他们自己的假工厂的单元测试。解决方案看起来像这样(暂时忽略泛型):

public class ISomeFactory { ... }

public class DefaultSomeFactory: ISomeFactory { ... }

public class ClientClass
{
    public ISomeFactory FactoryOfSome  // Right place for dependency injection
    {
        get
        {
            if (_fact == null)
                _fact = new DefaultFactory();
            return _fact;
        }
        set { _fact = value; }
    }
    private ISomeFactory _fact;
}

现在正如我所说,您的类使用泛型参数MyClass<T>,然后工厂也应该使用泛型参数:Factory<T>. 这个解决方案比一般工厂的通用方法要好,仅仅是因为创建一个实例可能是T特定的。通用工厂的解决方案允许您这样做:

public class SpecialSomeFactory: DefaultSomeFactory<string> { ... }

通过这种方式,您可以覆盖现有工厂类的行为,并有另一种方法来生成专用于字符串的实例。这很重要,因为处理字符串通常与处理 int 或 double 等原始类型有很大不同。有机会使工厂专业化可能是有益的。但是现在你明白了为什么拥有一个静态工厂可能是个坏主意——静态不能被扩展。

于 2013-05-21T10:11:56.070 回答
1

这两个示例本质上都是服务定位器模式的变体。有争议的是,这通常被认为是一种反模式,因为使用它的类的依赖项对其消费者不可见。

使您的依赖关系更明确的一种方法是采用类似于第一个示例的解决方案,但创建CreateNew()一个实例方法,而不是静态方法。

于 2013-05-21T10:48:46.733 回答