Design patterns 如何初始化工厂?
我有一个制造汽车的工厂。。。它是一个基本工厂,它接受一辆汽车的名称,查找实现ICar的所有类,根据汽车名称选择正确的类型,并使用反射初始化汽车Design patterns 如何初始化工厂?,design-patterns,dependency-injection,inversion-of-control,factory-pattern,Design Patterns,Dependency Injection,Inversion Of Control,Factory Pattern,我有一个制造汽车的工厂。。。它是一个基本工厂,它接受一辆汽车的名称,查找实现ICar的所有类,根据汽车名称选择正确的类型,并使用反射初始化汽车 public class CarFactory { Dictionary<string, Type> cars; public ICar CreateInstance(string carName) { // choose type of class from all classes that imp
public class CarFactory
{
Dictionary<string, Type> cars;
public ICar CreateInstance(string carName)
{
// choose type of class from all classes that implement ICar
Type t = GetTypeToCreate(carName);
return Activator.CreateInstance(t) as ICar;
}
// some more code...
}
公共级汽车制造厂
{
字典车;
公共ICar CreateInstance(字符串carName)
{
//从实现ICar的所有类中选择类的类型
类型t=GetTypeToCreate(carName);
将Activator.CreateInstance(t)作为ICar返回;
}
//更多的代码。。。
}
现在,我有一个使用汽车工厂的服务。在我的服务中初始化CarFactory
的正确方法是什么
一种解决方案是注入工厂,但工厂模式是IoC本身的一种形式,注入工厂感觉很奇怪。根据:
与IoC一起使用工厂没有多大意义,因为
IoC容器在某种意义上是“通用抽象工厂”
换句话说,根据我的经验,任何时候我想添加
工厂我以更简单的基于IoC的解决方案结束,所以我
敢说“国际奥委会杀了工厂之星”
以上这些对我来说是完全有意义的,尽管我还没有想到一个解决方案来用DI来取代我的工厂
所以我的问题是(对于那些使用工厂模式的人)我应该如何初始化它
为了避免问题太长,我在这个问题中使用了一个简化的CarFactory
示例。我发布了完整的示例。最好将依赖项(构造函数、属性、方法)注入到类型中。最好避免使用新运算符创建依赖项
为了使它更好,您应该为您定义一个接口CarFactory
(ICarFactory
),并将您的服务更改为依赖于该类型
在测试中,您可以模拟ICarFactory,并为您的测试用例提供特殊的实现。我认为比较依赖注入容器和工厂是错误的。
是的,两个职责都是创建某种类型的实例
但DI容器负责根据DI配置实例化实例及其所有依赖项。通常DI容器实例化应用程序入口点中的对象(main
method或web应用程序中的request
)
其中,Factory将基于应用程序的某些业务逻辑或仅在运行时可访问的某些值创建类型的实例
Factory和其他类一样是普通类,可以将其作为依赖项注入
在您的特定情况下,您只在运行时知道汽车的名称,因此您需要一些类,这些类的职责是将汽车的名称“转换”为汽车的实例。像往常一样,对于这类问题,答案是,这取决于™。这取决于您试图解决的问题。虽然此问题同时带有依赖项注入和控制反转(在一定程度上),但这些都不是目标本身,而只是实现适当目标的一种手段
通常,目标是行为脱钩。这会引出第一个问题,然后:
为什么CreateInstance
返回ICar
实例
这里我假设ICar
是一个接口。ICar
是多态的吗?这个接口有多个实现吗
对我来说,名为car的对象听起来像一个实体,因为它们通常表示数据,而不是行为
不过,为了便于讨论,让我们假设ICar
确实是多态的
如图所示,CarFactory
看起来是确定性的。但很难说,因为没有显示整个实现。但是,如果是,为什么它甚至需要初始化
它难道不能只是一个静态函数吗
public static class CarFactory
{
public static ICar CreateInstance(string carName)
{
// choose type of class from all classes that implement ICar
Type t = GetTypeToCreate(carName);
return Activator.CreateInstance(t) as ICar;
}
// some more code...
}
非常感谢。是的,我会使用ICarFactory进行DI…所以工厂注入是一种常见做法?只是想确保我所做的不是设计气味或类似的东西?@Hooman我经常注入工厂抽象(IFactory)我不认为这是一个设计缺陷或气味。你也可以在IOC容器中注册你的汽车,并在ICarFactory后面使用它为你提供所需的汽车实例。再次感谢…我更新了我的问题,并提供了一些参考,建议不要注入工厂…事实上,不要在第一个pl使用工厂模式ace…我开始认为我的问题可能是基于意见的。>我开始认为我的问题可能是基于意见的,这是真的:-)。我会说,使用最适合您的解决方案的方法,但始终使用接口和注入依赖项。引用中说,工厂和DI容器做相同的工作,您不需要为一项工作同时使用这两种工具b、 因此,您的问题的答案是没有正确的方法来初始化工厂。不要使用工厂。使用DI容器。@jaco0646:谢谢。如果是这种情况,那么工厂的注入就被排除了……可以公平地说,使用静态工厂是一种方法吗(与在构造函数中实例化工厂相反)?就像静态DI容器一样?你说的“初始化”是什么意思?@MarkSeemann:谢谢,我的意思是我应该使用静态工厂,在服务的构造函数中实例化工厂还是注入工厂?非常感谢FabioThanks。是的,ICar是多态的,Car是我的视图模型。我试图避免一篇长文章,因此简化了我的code、 我更新了这个问题,在上面的答案中添加了一个与实际代码的链接。你说:“一个名为car的对象在我看来像一个实体,通常不应该被注入,因为它们通常代表数据,而不是行为。”我读过你的另一个答案,这个答案是链接的,但你在这里解释实体不应该被注入