引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。

曾经有人告诉我,你如何使用它才会有所不同!

我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。

谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?


当前回答

当您确切地知道此时需要什么类型的对象时,就可以使用依赖项注入。而在工厂模式的情况下,你只是把创建对象的过程委托给工厂,因为你不清楚你需要什么类型的对象。

其他回答

我建议保持概念的简单明了。依赖注入更像是一种松散耦合软件组件的体系结构模式。工厂模式只是将创建其他类的对象的职责分离给另一个实体的一种方法。工厂模式可以被称为实现依赖注入的工具。依赖注入可以通过多种方式实现,比如使用构造函数进行依赖注入,使用映射xml文件等。

我知道这个问题很老了,但我想补充一下我的观点,

我认为依赖注入(DI)在很多方面类似于可配置的工厂模式(FP),从这个意义上说,你可以用DI做任何事情,你也可以用这样的工厂来做。

实际上,如果你使用spring为例,你可以选择自动装配资源(DI)或做这样的事情:

MyBean mb = ctx.getBean("myBean");

然后使用'mb'实例来做任何事情。这不是一个对工厂的调用,它将返回一个实例吗??

我注意到的大多数FP示例之间唯一真正的区别是,您可以在xml或其他类中配置“myBean”是什么,框架将作为工厂工作,但除此之外是一样的事情,您当然可以有一个工厂来读取配置文件或根据需要获得实现。

如果你问我的意见(我知道你没有),我相信DI做了同样的事情,但只是增加了开发的复杂性,为什么?

嗯,首先,为了让您知道用于DI自动装配的任何bean的实现是什么,您必须进入配置本身。

但是…您不必知道正在使用的对象的实现,这种承诺又如何呢?啐!严重吗?当你使用这样的方法时……你不就是写实现的那个人吗??即使你没有,你不是几乎所有的时间都在看如何实现它应该做什么??

最后一点,不管DI框架向你承诺了多少,你将构建与它解耦的东西,不依赖于它们的类,如果你正在使用一个框架,你将围绕它构建一切,如果你不得不改变方法或框架,这将不是一个简单的任务……!…但是,由于您围绕特定的框架构建所有内容,而不是担心什么是最适合您的业务的解决方案,那么在这样做时,您将面临一个更大的问题。

事实上,我所能看到的FP或DI方法的唯一真正的业务应用是,如果你需要在运行时改变正在使用的实现,但至少我所知道的框架不允许你这样做,你必须在开发时让所有的配置都完美无缺,如果你需要使用另一种方法。

因此,如果我有一个类,它在同一个应用程序的两个作用域中执行不同的操作(比如说,同一个公司的两个控股公司),我必须配置框架来创建两个不同的bean,并调整我的代码以使用每个bean。这是不是和我只是写这样的东西是一样的

MyBean mb = MyBeanForEntreprise1(); //In the classes of the first enterprise
MyBean mb = MyBeanForEntreprise2(); //In the classes of the second enterprise

和这个一样:

@Autowired MyBean mbForEnterprise1; //In the classes of the first enterprise
@Autowired MyBean mbForEnterprise2; //In the classes of the second enterprise

这:

MyBean mb = (MyBean)MyFactory.get("myBeanForEntreprise1"); //In the classes of the first enterprise
MyBean mb = (MyBean)MyFactory.get("myBeanForEntreprise2"); //In the classes of the second enterprise

在任何情况下,您都必须更改应用程序中的某些内容,无论是类还是配置文件,但您必须重新部署它。

这样做不是很好吗?

MyBean mb = (MyBean)MyFactory.get("mb"); 

通过这种方式,您可以设置工厂的代码以在运行时获得正确的实现,这取决于登录的用户企业??这很有帮助。您只需添加一个带有新类的新jar,并在运行时设置规则(或者如果您保留此选项,则添加一个新的配置文件),无需更改现有类。这将是一个动态工厂!

这不是比为每个企业编写两个配置,甚至为每个企业编写两个不同的应用程序更有帮助吗?

You can tell me, I don't need to do the switch at runtime ever, so I configure the app, and if I inherit the class or use another implementation I just change the config and redeploy. Ok, that can also be done with a factory. And be honest, how many times do you do this? maybe only when you have an app that's going to be used somewhere else in your company, and you are going to pass the code to another team, and they will do things like this. But hey, that can also be done with the factory, and would be even better with a dynamic factory!!

不管怎样,评论区是开放的,你可以杀了我。

从表面上看,他们是一样的

简单来说,工厂模式,创建模式帮助我们创建一个对象——“定义一个创建对象的接口”。如果我们有一个键值类型的对象池(例如Dictionary),将键传递给工厂(我指的是简单工厂模式),您可以解析类型。完成工作! 另一方面,依赖注入框架(如结构图、Ninject、Unity等)似乎也在做同样的事情。

但是…“不要白费力气”

从架构的角度来看,这是一个绑定层,“不要白费力气”。

对于企业级应用程序,依赖注入的概念更像是一个定义依赖关系的体系结构层。为了进一步简化,您可以将其视为一个单独的类库项目,它进行依赖解析。主应用程序依赖于这个项目,其中依赖项解析器引用其他具体实现和依赖项解析。

除了来自Factory的“GetType/Create”之外,我们通常还需要更多的特性(使用XML定义依赖关系、模拟和单元测试等)。既然您引用了结构图,那么请查看结构图特性列表。这显然不仅仅是解决简单的对象映射。别白费力气了!

如果你只有一把锤子,那么所有东西看起来都像钉子

根据您的需求和您构建的应用程序类型,您需要做出选择。如果它只有很少的项目(可能是一个或两个..)并且涉及很少的依赖项,您可以选择一个更简单的方法。这就像使用ADO . net数据访问而不是使用实体框架进行简单的1或2个数据库调用,在这种情况下引入EF是多余的。

但是对于一个更大的项目,或者如果你的项目变得更大,我强烈建议有一个带有框架的DI层,并留出空间来改变你使用的DI框架(在主应用程序中使用Facade (Web应用程序,Web Api, Desktop..等)。

在我看来,使用依赖注入更好,如果你是: 1. 将代码部署在小分区中,因为它可以很好地解耦一个大代码。 2. 可测试性是DI可以使用的情况之一,因为你可以很容易地模拟非去耦的对象。通过使用接口,您可以轻松地模拟和测试每个对象。 3.你可以同时修改程序的每一部分,而不需要编码它的另一部分,因为它是松散解耦的。

简单来说,依赖注入和工厂方法分别意味着推和拉机制。

拉机制:类间接依赖于工厂方法,工厂方法又依赖于具体类。

推送机制:根组件可以在一个位置配置所有依赖组件,从而促进高维护和松耦合。

使用Factory方法时,创建新对象的责任仍然由类承担(尽管是间接的),而使用依赖注入时,责任是外包的(尽管是以泄露抽象为代价)。