我有一个泛型类,我们称之为MyClass<T>
,它需要有一个工厂方法,以便从客户端代码中抽象构造函数细节。
这两个选项中哪一个是正确的? (包括示例实例化代码)
原始通用 MyClass<T>
上的静态非通用工厂方法:
MyClass<SomeType> instance = MyClass<SomeType>.CreateNew();
MyClass
实施中的静态通用工厂方法:
MyClass<SomeType> instance = MyClass.CreateNew<SomeType>();
答案 0 :(得分: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)有很大不同。有机会专业化工厂可能是有益的。但现在你明白为什么拥有一个静态工厂可能是一个坏主意 - 无法扩展静态。
答案 1 :(得分:1)
这两个示例基本上都是服务定位器模式的变体。有争议的是,这通常被认为是反模式,因为使用它的类的依赖关系对其消费者是不可见的。
使依赖关系更加明确的一种方法是采用类似于第一个示例的解决方案,但使CreateNew()
成为实例方法,而不是静态方法。