Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 months ago.
The community reviewed whether to reopen this question 7 months ago and left it closed:
Original close reason(s) were not resolved
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(30)
DI 的一个缺点是它不能用逻辑初始化对象。 例如,当我需要创建一个具有随机名称和年龄的角色时,DI 不是工厂模式的选择。 使用工厂,我们可以轻松地封装对象创建中的随机算法,这支持称为“封装变化的内容”的设计模式之一。
One disadvantage of DI is that it can not initialize objects with logic. For example, when I need to create a character that has random name and age, DI is not the choice over factory pattern. With factories, we can easily encapsulate the random algorithm from object creation, which supports one of the design patterns called "Encapsulate what varies".
来自:http://tutorials.jenkov.com/dependency-注入/dependency-injection-containers.html
From: http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html
理论
有两点需要考虑:
如何在单个项目中使用工厂和依赖注入的实际示例
应用程序用于创建订单的模块,其中包含多个称为订单行的条目。
假设我们要创建以下分层架构:
域对象可以是存储在数据库内的对象。
存储库 (DAO) 有助于从数据库中检索对象。
服务为其他模块提供API。 允许对
order
模块进行操作。将在数据库中的实体是Order和OrderLine。 订单可以有多个订单行。
现在是重要的设计部分。 该模块之外的模块是否应该自行创建和管理 OrderLines? 不可以。只有当您有与之关联的订单时,订单行才应存在。 如果您可以向外部类隐藏内部实现,那就最好了。
但是如何在不了解 OrderLines 的情况下创建订单呢?
Factory
想要创建新订单的人使用 OrderFactory (它将隐藏有关我们如何创建订单的事实的详细信息)。
这就是它在 IDE 中的样子。
domain
包外部的类将使用OrderFactory
而不是Order
内的构造函数。依赖注入更常用于无状态层,例如存储库和服务。
OrderRepository 和 OrderService 由依赖注入框架管理。
存储库负责管理数据库上的 CRUD 操作。 服务注入存储库并使用它来保存/查找正确的域类。
Theory
There are two important points to consider:
Practical example on how to use both factory and dependency injection in a single project
Application module for creating order which contains multiple entries called orderline.
Let's assume we want to create the following layered architecture:
Domain objects may be objects stored inside the database.
Repository (DAO) helps with retriever of objects from the database.
Service provides API to other modules. Allows for operations on
order
module.Entities which will be in the database are Order and OrderLine. Order can have multiple OrderLines.
Now comes the important design part. Should modules outside this one create and manage OrderLines on their own? No. Order Line should exist only when you have Order associated with it. It would be best if you could hide internal implementation to outside classes.
But how to create Order without knowledge about OrderLines?
Factory
Someone who wants to create new order used OrderFactory (which will hide details about the fact how we create Order).
That's how it will look like inside an IDE. Classes outside the
domain
package will useOrderFactory
instead of constructor insideOrder
.Dependency injection is more commonly used with stateless layers such as repository and service.
OrderRepository and OrderService are managed by the dependency injection framework.
Repository is responsible for managing CRUD operations on the database. Service injects Repository and uses it to save/find correct domain classes.
我相信 DI 是工厂的一种抽象层,但它们还提供了抽象之外的好处。 真正的工厂知道如何实例化单个类型并配置它。 良好的 DI 层通过配置提供了实例化和配置多种类型的能力。
显然,对于类型较少、构建时需要相对稳定的业务逻辑的项目来说,工厂模式易于理解、实现且效果良好。
OTOH,如果您有一个包含多种类型的项目,您希望经常更改其实现,DI 可以通过其配置为您提供灵活性,让您可以在运行时执行此操作,而无需重新编译工厂。
I believe DI is a type of abstraction layer on factories, but they also provide benefits beyond abstraction. A true factory knows how to instantiate a single type and configure it. A good DI layer provides the ability, through configuration, to instantiate and configure many types.
Obviously, for a project with a few simple types that requires relatively stable business logic in their construction, the factory pattern is simple to understand, implement, and works well.
OTOH, if you have a project containing numerous types whose implementations you expect to change often, DI gives you the flexibility through its configuration to do this at runtime without having to recompile your factories.
我知道这个问题很老了,但我想补充我的五美分,
我认为依赖注入(DI)在很多方面都像可配置工厂模式(FP),从这个意义上说,你可以用 DI 做的任何事情你都会有这样的工厂就能做到。
实际上,例如,如果您使用 spring,您可以选择自动装配资源 (DI) 或执行类似以下操作:
然后使用该“mb”实例执行任何操作。 这不是对工厂的调用会返回一个实例吗?
我注意到大多数 FP 示例之间唯一真正的区别是,您可以在 xml 或另一个类中配置“myBean”,并且框架将作为工厂工作,但除此之外是相同的事情,并且您当然可以有一个工厂来读取配置文件或根据需要获取实现。
如果你问我的意见(我知道你没有),我相信 DI 做了同样的事情,但只是增加了开发的复杂性,为什么?
好吧,一方面,为了让您知道使用 DI 自动装配的任何 bean 所使用的实现是什么,您必须转到配置本身。
但是...您不必知道您正在使用的对象的实现的承诺又如何呢? 噗! 严重地? 当你使用这样的方法时......你不就是编写实现的人吗? 即使你不这样做,你不是一直在关注实现如何完成它应该做的事情吗?
最后一件事,DI 框架向您承诺多少并不重要,您将构建与它解耦的东西,并且不依赖于它们的类,如果您正在使用一个框架,你围绕它构建一切,如果你必须改变方法或框架,这将不是一件容易的任务......永远!......但是,因为你围绕它构建一切如果您选择特定的框架,而不是担心什么是最适合您业务的解决方案,那么您在这样做时将面临很大的问题。
事实上,我能看到的 FP 或 DI 方法的唯一真正的业务应用程序是您是否需要更改在运行时使用的实现,但至少我知道的框架不允许您这样做为此,您必须在开发时使配置中的所有内容保持完美,如果需要,请使用其他方法。
因此,如果我有一个类在同一应用程序的两个范围内执行不同的操作(比如说,一家控股公司),我必须配置框架来创建两个不同的 bean,并调整我的代码以使用每个 bean。 这不是就像我写这样的东西一样吗:
与这样的一样:
而且这样:
在任何情况下,您都必须更改应用程序中的某些内容,无论是类还是配置文件,但您都必须这样做重新部署它。
做这样的事情不是很好吗:
这样,您可以设置工厂的代码以根据登录的用户企业在运行时获得正确的实现? 现在这会有帮助的。 您只需添加一个包含新类的新 jar 并设置规则,甚至可以在运行时设置(或者如果您将此选项保持打开状态,则添加一个新的配置文件),无需更改现有类。 这将是一个动态工厂!
这不是比必须为每个企业编写两个配置,甚至可能每个企业有两个不同的应用程序更有帮助吗?
您可以告诉我,我不需要在运行时进行切换,因此我配置应用程序,如果我继承该类或使用其他实现,我只需更改配置并重新部署。 好吧,这也可以通过工厂来完成。 老实说,你这样做了多少次? 也许只有当您有一个将在公司其他地方使用的应用程序,并且您要将代码传递给另一个团队时,他们才会做这样的事情。 但是,嘿,这也可以通过工厂来完成,并且如果使用动态工厂会更好!
无论如何,如果评论区开放,你就杀了我吧。
I know this question is old but i would like to add my five cents,
I think that dependency injection (DI) is in many ways like a configurable Factory Pattern (FP), and in that sense anything that you could do with DI you will be able to do it with such factory.
Actually, if you use spring for example, you have the option of autowiring resources (DI) or doing something like this:
And then use that 'mb' instance to do anything. Isn't that a call to a factory that will return you an instance??
The only real difference I notice between most of the FP examples is that you can configure what "myBean" is in an xml or in another class, and a framework will work as the factory, but other than that is the same thing, and you can have a certainly have a Factory that reads a config file or gets the implementation as it needs.
And if you ask me for my opinion (And I know you didn't), I believe that DI does the same thing but just adds more complexity to the development, why?
well, for one thing, for you to know what is the implementation being used for any bean you autowire with DI, you have to go to the configuration itself.
but... what about that promise that you will not have to know the implementation of the object you are using? pfft! seriously? when you use an approach like this... aren't you the same that writes the implementation?? and even if you don't, arent you almost all the time looking at how the implementation does what it is supposed to do??
and for one last thing, it doesn't matter how much a DI framework promises you that you will build things decoupled from it, with no dependencies to their classes, if you are using a framework you build everything aroud it, if you have to change the approach or the framework it will not be an easy task... EVER!... but, since you buil everything around that particular framework instead of worrying of whats the best solution for your business, then you will face a biiig problen when doing that.
In fact, the only real business application for a FP or DI approach that I can see is if you need to change the implementations being used at runtime, but at least the frameworks I know do not allow you to do that, you have to leave everything perfect in the configuration at development time an if you need that use another approach.
So, if I have a class that performs differently in two scopes in the same application (lets say, two companies of a holding) I have to configure the framework to create two different beans, and adapt my code to use each. Isn't that the same as if I would just write something like this:
the same as this:
And this:
In any case you will have to change something in your application, whether classes or configuration files, but you will have to do it an redeploy it.
Wouldn't it be nice to do just something like this:
And that way, you set the code of the factory to get the right implementation at runtime depending on the logged user enterprise?? Now THAT would be helpful. You could just add a new jar with the new classes and set the rules maybe even also at runtime (or add a new config file if you leave this option open), no changes to existing classes. This would be a Dynamic factory!
wouldn't that be more helpful than having to write two configurations for each enterprise, and maybe even having two different applications for each??
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!!
Anyway, the comment section if open for you to kill me.
IOC 是一个通过两种方式实现的概念。 依赖创建和依赖注入、工厂/抽象工厂是依赖创建的例子。 依赖注入是构造函数、setter 和接口。 IOC的核心是不依赖于具体类,而是定义方法的抽象(例如接口/抽象类)并使用该抽象来调用具体类的方法。 像工厂模式一样返回基类或接口。 类似地,依赖注入使用基类/接口来设置对象的值。
IOC is a concept which is implemented by two ways. Dependency creation and dependency injection, Factory/Abstract factory are the example of dependency creation. Dependency injection is constructor, setter and interface. The core of IOC is to not depend upon the concrete classes, but define the abstract of methods(say an Interface/abstract class) and use that abstract to call method of concrete class. Like Factory pattern return the base class or interface. Similariliy dependency injection use base class/interface to set value for objects.
使用依赖注入框架,开发人员不需要手动准备和设置类实例的依赖关系,所有这些都已提前准备好。
对于工厂,开发人员必须手动执行此操作并使用这些依赖对象创建类实例。
区别主要在于调用工厂并获取构造对象的这一行,以及编写创建和设置所有内容的工厂方法(尽管可以说,使用依赖注入框架,这也必须对在一定程度上,通过连接和配置对象关系)。
然后,对于工厂,您必须在需要此类对象的任何地方调用工厂。
使用 DI 框架,您主要可以依赖在类实例创建时就已经存在的对象。
我的观点是,工厂方法更加静态,因为它的实现相当固定,而依赖注入框架更加动态,因为类实例的实际组成可以在运行时更容易地更改(例如,出于测试目的)。
With a dependency injection framework the developer does not need to prepare and set dependencies of a class instance manually, it's all prepared beforehand.
With factories, the developer has to do this by hand and create the classes instance using those dependent objects.
The difference lies mostly in this one line where calling the factory and fetching the constructed object is done and in writing the factory method that creates and sets up everything (although it could be argued that with dependency injection frameworks this has also to be done to a certain extend, by wiring up and configuring the object relations).
Then with factories you have to call the factory everywhere you need such an object.
With DI frameworks you mostly can rely on the presence of the object already at creation time of the class instance.
My opinion is that a factory method is more static as its implementation is rather fixed while a dependency injection framework is more dynamic as the actual composition of a class instance can change more easily (eg. for testing purposes) at runtinme.
我的想法:
依赖注入:将协作者作为参数传递给构造函数。
依赖注入框架:一个通用且可配置的工厂,用于创建对象并作为参数传递给构造函数。
My thoughts:
Dependecy Injection: pass collaborators as parameters to the constructors.
Dependency Injection Framework: a generic and configurable factory to create the objects to pass as parameters to the constructors.
当我读到 DI 并最终看到这篇文章时,我也有同样的问题。
最后这就是我的理解,如果有错误请纠正我。
“很久以前,有一些小王国,有自己的管理机构,根据自己的成文规则进行控制和决策。后来形成了一个大政府,消除了所有这些小管理机构,这些机构有一套规则(宪法)并通过法院执行”
小王国的管理机构是“工厂”,
大政府是“依赖注入器”。
I had the same question as soon as I read about DI and ended up at this post.
So finally this is what I understood but please correct me if am wrong.
"Long ago there were little kingdoms with their own governing bodies controlling and taking decisions based on their own written rules. Later on formed a big government eliminating all these little governing bodies which has one set of rules(constitution) and are implemented through courts"
The little kingdoms' governing bodies are "Factories"
The big government is the "Dependency Injector".
您可以查看此链接 在实际示例中比较两种(和其他)方法。
基本上,当需求发生变化时,如果使用工厂而不是 DI,最终会修改更多代码。
这对于手动 DI 也有效(即,当没有外部框架为您的对象提供依赖项,但您在每个构造函数中传递它们时)。
You can have a look at this link for a comparison of the two (and others) approaches in a real example.
Basically, when requirements change, you end up modifying more code if you use factories instead of DI.
This is also valid with manual DI (i.e. when there isn't an external framework that provides the dependencies to your objects, but you pass them in each constructor).
这里的大多数答案都解释了两者的概念差异和实现细节。 然而,我无法找到关于应用程序差异的解释,IMO 是最重要的,并且 OP 询问了这一点。 那么让我重新开始这个话题......
确切地。 在 90% 的情况下,您可以使用 Factory 或 DI 获取对象引用,通常最终会得到后者。 在另外 10% 的情况下,使用 Factory 是唯一正确的方法。 这些情况包括通过运行时参数变量获取对象。 像这样:
在这种情况下,从 DI 获取
client
是不可能的(或者至少需要一些丑陋的解决方法)。 因此,作为做出决定的一般规则:如果可以在没有任何运行时计算参数的情况下获得依赖项,则首选 DI,否则使用 Factory。Most answers here explain conceptual difference and implementation details of both. However I was unable to find explanation about difference in application which IMO is the most important and the OP asked about. So let me reopen this topic...
Exactly. In 90% cases you can obtain object reference using either Factory or DI and usually you end up with latter. In another 10% cases using Factory is only correct way. These cases include obtaining objects by variable at runtime parameters. Like this:
In this case getting
client
from DI is not possible (or at least requires some ugly workaround). So as a general rule to make decision: if a dependency can be obtained without any runtime calculated parameters then DI is preferred, otherwise use Factory.通过工厂,您可以对相关接口进行分组,因此,如果传递的参数可以在工厂中进行分组,那么它也是构造函数过度注入的一个很好的解决方案,看看这段代码*):
看看构造函数,您只需必须在那里传递
IAddressModelFactory
,因此参数较少*):您在
CustomerController
中看到传递了很多参数,是的,您可以将其视为构造函数过度注入 但这就是 DI 的工作原理。
CustomerController
也没有任何问题。*) 代码来自 nopCommerce。
With a factory you can group related interfaces, So If the parameters passed can be grouped in a factory then its also a good solution for
constructor overinjection
look at this code *):Look at the constructor, you only have to pass the
IAddressModelFactory
there, so less parameters *):You see in
CustomerController
a lot of parameters passed, Yes you can see this asconstructor overinjection
but this is how DI works. And no nothing is wrong with theCustomerController
.*) Code is from nopCommerce.
简单来说,依赖注入与工厂方法分别意味着推与拉机制。
拉机制:类间接依赖于工厂方法,而工厂方法又依赖于具体类。
推送机制:根组件可以与所有依赖组件一起配置在一个位置,从而促进高维护性和松散耦合。
使用工厂方法,创建新对象的责任仍然在于类(尽管是间接的),而与依赖注入一样,该责任是外包的(尽管以泄漏抽象为代价)
In simple terms Dependency Injection vs Factory method implies push vs pull mechanism respectively.
Pull mechanism : class indirectly have dependency on Factory Method which in turn have dependency on concrete classes.
Push mechanism : Root component can be configured with all dependent components in a single location and thus promoting high maintenance and loose coupling.
With Factory method responsibility still lies with class (though indirectly) to create new object where as with dependency injection that responsibility is outsourced (at the cost of leaking abstraction though)
我相信 DI 是一种配置或实例化 bean 的方法。 DI 可以通过多种方式完成,例如构造函数、setter-getter 等。
工厂模式只是实例化 bean 的另一种方式。 这种模式主要用于当你必须使用工厂设计模式创建对象时,因为使用这种模式时你不需要配置bean的属性,只实例化对象。
检查此链接:依赖注入
i believe that DI is a way of configurings or instantianting a bean. The DI can be done in many ways like constructor, setter-getter etc.
Factory pattern is just another way of instantiating beans. this pattern will be used mainly when you have to create objects using factory design pattern,because while using this pattern you dont configure the properties of a bean, only instantiate the object.
Check this link :Dependency Injection
Binoj,
我认为你不必选择其中之一。
将依赖类或接口移动到类构造函数或设置器的行为遵循 DI 模式。 传递给构造函数或集合的对象可以使用 Factory 来实现。
什么时候使用? 使用开发人员掌握的模式。 他们觉得什么最舒服并且最容易理解。
Binoj,
I don't think you have to choose one over the other.
The act of moving a dependent class or interface to a class constructor or setter follows the DI pattern. The object you pass to the constructor or set can be implemented with Factory.
When to use? Use the pattern or patterns that are in your developer wheelhouse. What do they feel the most comfortable with and find easiest to understand.
我相信,控制对象及其使用的三个重要方面:
1. 实例化(类的实例化以及初始化(如果有的话))。
2. 在需要的地方注入(如此创建的实例)。
3.(如此创建的实例的)生命周期管理。
使用工厂模式,实现了第一个方面(实例化),但其余两个方面是有问题的。 使用其他实例的类必须对工厂进行硬编码(而不是创建实例),这会阻碍松散耦合的能力。 此外,实例的生命周期管理在多个地方使用工厂的大型应用程序中成为一个挑战(特别是,如果工厂不管理它返回的实例的生命周期,它就会丑陋的)。
另一方面,使用 DI(IoC 模式),所有这 3 个都被抽象到代码外部(到 DI 容器),并且托管 bean 不需要这种复杂性。 松耦合,一个非常重要的架构目标,可以安静舒适地实现。 另一个重要的架构目标,关注点分离可以比工厂更好地实现。
虽然工厂可能适合小型应用程序,但大型应用程序最好选择 DI 而不是工厂。
I believe, 3 important aspects govern objects and their usage:
1. Instantiation (of a class together with initialisation if any).
2. Injection (of the instance so created) where it's required.
3. Life cycle management (of the instance so created).
Using Factory pattern, the first aspect (instantiation) is achieved but the remaining two is questionable. The class that uses other instances must hardcode the factories (instead of instances being created) which hinders loose coupling abilities. Moreover, life cycle management of instances becomes a challenge in a large application where a factory is used in multiple places (particularly, if the factory doesn't manage the life cycle of the instance it returns, it gets ugly).
Using a DI (of IoC pattern) on the other hand, all the 3 are abstracted outside the code (to the DI container) and the managed bean needs nothing about this complexity. Loose Coupling, a very important architectural goal can be achieved quiet comfortably. Another important architectural goal, the separation of concerns can be achieved much better than factories.
Whereas the Factories may be suitable for small applications, large ones would be better to chose DI over factories.
当您确切地知道此时需要什么类型的对象时,您可以使用依赖项注入。 而在工厂模式的情况下,您只需将创建对象的过程委托给工厂,因为您不清楚所需的对象的确切类型。
You use dependency injection when you exactly know what type of objects you require at this point of time. While in case of factory pattern, you just delegate the process of creating objects to factory as you are unclear of what exact type of objects you require.
注入框架是工厂模式的实现。
这完全取决于您的要求。 如果您需要在应用程序中实现工厂模式,那么无数的注入框架实现之一很可能可以满足您的要求。
仅当任何第三方框架无法满足您的要求时,您才应该推出自己的解决方案。 您编写的代码越多,需要维护的代码就越多。 代码是一种负债而不是资产。
关于应该使用哪种实现的争论并不像理解应用程序的架构需求那么重要。
An Injection Framework is an implementation of the Factory Pattern.
It all depends upon your requirements. If you have need to implement the factory pattern in an application, it's highly likely your requirements will be met by one of the myriad of injection framework implementations out there.
You should only roll out your own solution if your requirements cannot be met by any of the 3rd party frameworks. The more code you write, the more you code you have to maintain. Code is a liability not an asset.
Arguments over which implementation you should use is not as fundamentally important as understanding the architectural needs of your application.
工厂设计模式
工厂设计模式的特点是
当你问自己如下时,你可以观察到一些事情
这些是通过依赖注入处理的。
依赖项注入
您可以采用不同的方式来注入依赖项。 为了简单起见,我们使用接口注入
在 DI 中,容器创建所需的实例,并将它们“注入”到对象中。
从而消除了静态实例化。
例子:
Factory Design Pattern
The factory design pattern is characterized by
You can observe few things when you question yourself as below
These are handled by Dependency injection.
Dependency injection
You can have different ways in which you can inject dependency. For simplicity lets go with Interface Injection
In DI ,container creates the needed instances, and "injects" them into the object.
Thus eliminates the static instantiation.
Example:
从表面上看,它们看起来相同
用非常简单的术语来说,工厂模式,一种创建模式可以帮助我们创建一个对象 - “定义一个用于创建对象的接口”。 如果我们有一个键值排序的对象池(例如字典),将键传递给工厂(我指的是简单工厂模式)就可以解析类型。 任务完成!
另一方面,依赖注入框架(例如 Structure Map、Ninject、Unity 等)似乎也在做同样的事情。
但是......“不要重新发明轮子”
从架构的角度来看,它是一个绑定层和“不要重新发明轮子”。
对于企业级应用程序,DI 的概念更多的是定义依赖关系的架构层。 为了进一步简化,您可以将其视为一个单独的类库项目,它执行依赖关系解析。 主要应用程序依赖于该项目,其中依赖关系解析器引用其他具体实现和依赖关系解析。
除了从工厂“GetType/Create”之外,我们通常还需要更多功能(使用 XML 定义依赖项、模拟和单元测试等的能力)。 由于您提到了结构图,请查看结构图功能列表 。 它显然不仅仅是解决简单的对象映射。 不要重新发明轮子!
如果您只有一把锤子,那么一切看起来都像钉子
根据您的要求以及您构建的应用程序类型,您需要做出选择。 如果它只有几个项目(可能是一两个......)并且涉及很少的依赖项,您可以选择一种更简单的方法。 这就像使用 ADO .Net 数据访问而不是使用实体框架进行简单的 1 或 2 个数据库调用,在这种情况下引入 EF 是一种过度杀伤力。
但对于较大的项目或者如果您的项目变得更大,我强烈建议您拥有一个带有框架的 DI 层,并腾出空间来更改您使用的 DI 框架(在主应用程序中使用外观(Web 应用程序、Web Api、桌面) ..ETC。)。
From a face value they look same
In very simple terms, Factory Pattern, a Creational Pattern helps to create us an object - "Define an interface for creating an object". If we have a key value sort of object pool (e.g. Dictionary), passing the key to the Factory (I am referring to the Simple Factory Pattern) you can resolve the Type. Job done!
Dependency Injection Framework (such as Structure Map, Ninject, Unity ...etc) on the other hand seems to be doing the same thing.
But... "Don't reinvent the wheel"
From a architectural perspective its a binding layer and "Don't reinvent the wheel".
For an enterprise grade application, concept of DI is more of a architectural layer which defines dependencies. To simplify this further you can think of this as a separate classlibrary project, which does dependency resolving. The main application depends on this project where Dependency resolver refers to other concrete implementations and to the dependency resolving.
Inaddition to "GetType/Create" from a Factory, most often than not we need more features (ability to use XML to define dependencies, mocking and unit testing etc.). Since you referred to Structure Map, look at the Structure Map feature list. It's clearly more than simply resolving simple object Mapping. Don't reinvent the wheel!
If all you have is a hammer, everything looks like a nail
Depending on your requirements and what type of application you build you need to make a choice. If it has just few projects (may be one or two..) and involves few dependencies, you can pick a simpler approach. It's like using ADO .Net data access over using Entity Framework for a simple 1 or 2 database calls, where introducing EF is an overkill in that scenario.
But for a larger project or if your project gets bigger, I would highly recommend to have a DI layer with a framework and make room to change the DI framework you use (Use a Facade in the Main App (Web App, Web Api, Desktop..etc.).
我认为这些是正交的并且可以一起使用。 让我向您展示一个我最近在工作中遇到的示例:
我们在 Java 中使用 Spring 框架进行 DI。 单例类 (
Parent
) 必须实例化另一个类 (Child
) 的新对象,并且这些对象具有复杂的协作者:在此示例中,
Parent
必须接收DepX
实例才能将它们传递给Child
构造函数。 与此相关的问题:Parent
对Child
的了解超出了应有的水平Parent
的协作者超出了应有的Child
添加了依赖项 code> 涉及更改Parent
这是我意识到
Factory
非常适合这里的时候:Child
类的除真实参数之外的所有参数,从Parent
可以看出,Child
的知识,可以集中在 DI 配置中。这是简化的
Parent
类和ChildFactory
类:I think these are orthogonal and can be used together. Let me show you an example I recently came across at work:
We were using the Spring framework in Java for DI. A singleton class (
Parent
) had to instantiate new objects of another class (Child
), and those had complex collaborators:In this example,
Parent
has to receiveDepX
instances only to pass them to theChild
constructor. Problems with this:Parent
has more knowledge ofChild
than it shouldParent
has more collaborators than it shouldChild
involves changingParent
This is when I realized a
Factory
would fit here perfectly:Child
class, as seen byParent
Child
, which can be centralized in the DI configuration.This is the simplified
Parent
class and theChildFactory
class:DI 为您提供组合根 ,这是用于连接对象图的单个集中位置。 这往往会使对象依赖关系变得非常明确,因为对象确切地要求它们需要什么,并且只有一个地方可以获取它。
组合根是一种干净、直接的关注点分离。 被注入的对象不应该依赖于 DI 机制,无论是第三方容器还是 DIY DI。 DI 应该是不可见的。
工厂往往更加分散。 不同的对象使用不同的工厂,工厂代表对象及其实际依赖关系之间的附加间接层。 这个附加层将其自己的依赖项添加到对象图中。 工厂并不是看不见的。 工厂是一个中间人。
因此,更新工厂会遇到更多问题:由于工厂是业务逻辑的依赖项,因此修改它们可能会产生连锁反应。 组合根不依赖于业务逻辑,因此可以单独修改它。
GoF 提到了更新抽象工厂的困难。 此处的答案引用了他们的部分解释。 将 DI 与工厂进行对比也与以下问题有很多共同点:ServiceLocator 是反模式吗?< /a>
最终,选择哪个答案可能是固执己见的; 但我认为这可以归结为工厂是一个中间人。 问题是,除了提供产品之外,中间商是否还通过增加附加价值来发挥作用。 因为如果你可以在没有中间商的情况下获得相同的产品,那么为什么不去掉中间商呢?
图表有助于说明差异。
DI gives you a composition root, which is a single centralized location for wiring up your object graph. This tends to make object dependencies very explicit, because objects ask for exactly what they need and there is only one place to get it.
A composition root is a clean and straightforward separation of concerns. Objects being injected should have no dependency on the DI mechanism, whether that be a third-party container or a DIY DI. The DI should be invisible.
Factories tend to be more distributed. Different objects use different factories and the factories represent an additional layer of indirection between the objects and their actual dependencies. This additional layer adds its own dependencies to the object graph. Factories are not invisible. A Factory is a middleman.
For this reason, updating factories is more problematic: since factories are a dependency of the business logic, modifying them can have a ripple effect. A composition root is not a dependency of the business logic, so it can be modified in isolation.
The GoF mentions the difficulty of updating Abstract Factories. Part of their explanation is quoted in an answer here. Contrasting DI with Factories also has a lot in common with the question, Is ServiceLocator an anti-pattern?
Ultimately, the answer of which to choose may be opinionated; but I think it boils down to a Factory being a middleman. The question is whether that middleman pulls its weight by adding additional value beyond just supplying a product. Because if you can get that same product without the middleman, then why not cut the middleman out?
A diagram helps to illustrate the difference.
[工厂]-> 有一个类可以根据请求参数创建类。 毕竟,“工厂”也在现实世界中为你制造“物体”。 您可以要求您的汽车供应商工厂制造(免费:))特斯拉版本。 1 给你。
[DI]-> 有一个(服务)容器,用于存储接口(契约类)。 您不关心创建对象。 您只需要求某人/某处实现它,细节和其他内容对您、呼叫者或消费者来说并不重要。
DI 是 SOLID 原则中“D”的基础。
[Factory] -> There is a class which creates classes based on request parameters. After all, a "factory" makes "objects" for you also in the real world. You can ask your car vendor factory to make (for free :) ) a Tesla ver. 1 for you.
[DI] -> There is a (service) container which stores interfaces (contracted classes). You don't care to create objects. You just ask someone/somwhere to implement it, details and other stuff do not matter to you, the caller or the consumer.
DI is at the base of the "D" in SOLID principles.
我使用两者来创建控制反转策略,为需要在我之后维护它的开发人员提供更多的可读性。
我使用工厂来创建不同的层对象(业务、数据访问)。
另一个开发人员会看到这一点,并且在创建业务层对象时,他会在 BusinessFactory 中查找,而 Intellisense 会为开发人员提供所有可能要创建的业务层。 不必玩游戏,找到我想要创建的界面。
这个结构已经是控制反转了。 我不再负责创建特定对象。 但您仍然需要确保依赖注入才能轻松更改内容。
创建自己的自定义依赖注入是荒谬的,所以我使用 Unity。 在 CreateCarBusiness() 中,我要求 Unity 解析哪个类属于该类及其生命周期。
所以我的代码工厂依赖注入结构是:
现在我拥有了两者的好处。 对于我使用的对象的范围,我的代码对于其他开发人员来说也更具可读性,而不是构造函数依赖注入,它只是说创建类时每个对象都可用。
当我创建单元测试时,我使用它来将数据库数据访问更改为自定义编码的数据访问层。 我不希望我的单元测试与数据库、网络服务器、电子邮件服务器等进行通信。他们需要测试我的业务层,因为那是智能所在。
I use both to create an Inversion Of Control strategy with more readability for developers who need to maintain it after me.
I use a Factory to create my different Layer objects (Business, Data Access).
Another developer will see this and when creating an Business Layer object he looks in BusinessFactory and Intellisense gives the developer all the possible Business Layers to create. Doesn't have to play the game, find the Interface I want to create.
This structure is already Inversion Of Control. I am no longer responsible for creating the specific object. But you still need to ensure Dependency Injection to be able to change things easily.
Creating your own custom Dependency Injection is ridiculous, so I use Unity. Within the CreateCarBusiness() I ask Unity to Resolve which class belongs to this and it’s lifetime.
So my code Factory Dependency Injection structure is:
Now I have the benefit of both. My code is also more readable for other developers as towards scopes of my objects I use, instead of Constructor Dependency Injection which just says every object is available when the class is created.
I use this to change my Database Data Access to a custom coded Data Access layer when I create Unit Tests. I don’t want my Unit Tests to communicate with databases, webservers, e-mail servers etc. They need to test my Business Layer because that’s where the intelligence is.
工厂模式帮助我们决定需要创建哪个对象,而依赖注入有助于注入具体对象。
两者是不同的。 我们可以根据工厂模式决定返回哪个对象。 我们可以使用依赖注入来返回对象,而不是使用 new 创建对象。 这样工厂模式就不会违反依赖注入。
Factory pattern help us in making decision which object needs to create whereas Dependency injection helps to inject the concrete object.
Both are different. We can decide which object to return based on factory pattern. We can use dependeny injection to return the object instead of creating the object using new. In this way, factory pattern will not violate dependeny injection.
使用工厂时,您的代码实际上仍然负责创建对象。 通过 DI,您可以将该责任外包给另一个类或框架,这些类或框架与您的代码是分开的。
When using a factory your code is still actually responsible for creating objects. By DI you outsource that responsibility to another class or a framework, which is separate from your code.
我建议保持概念简单明了。 依赖注入更多的是松散耦合软件组件的架构模式。 工厂模式只是将创建其他类的对象的责任分离到另一个实体的一种方法。 工厂模式可以被称为实现DI的工具。 依赖注入可以通过多种方式实现,例如使用构造函数的 DI、使用映射 xml 文件等。
I would suggest to keep the concepts plain and simple. Dependency Injection is more of a architectural pattern for loosely coupling software components. Factory pattern is just one way to separate the responsibility of creating objects of other classes to another entity. Factory pattern can be called as a tool to implement DI. Dependency injection can be implemented in many ways like DI using constructors, using mapping xml files etc.
依赖注入
汽车不会请求其运行所需的部件,而是实例化部件本身。
工厂
将各个部分组合在一起形成一个完整的对象,并向调用者隐藏具体类型。
结果
如您所见,工厂和 DI 是相辅相成的。
你还记得金发姑娘和三只熊吗? 嗯,依赖注入有点像那样。 以下是完成同一件事的三种方法。
示例#1 - 这是最糟糕的,因为它完全隐藏了依赖关系。 如果您将该方法视为黑匣子,您将不知道它需要汽车。
示例 #2 - 这更好一点,因为现在我们知道我们需要一辆车,因为我们经过了一家汽车工厂。 但这一次我们传递的太多了,因为该方法实际上需要的是一辆车。 我们传递一个工厂只是为了建造汽车,而汽车可以在方法之外建造并传入。
示例 #3 - 这是理想的选择,因为该方法要求准确 > 它需要什么。 不宜太多或太少。 我不必编写 MockCarFactory 来创建 MockCar,我可以直接传递模拟。它是直接的,接口不会说谎。
Misko Hevery 的 Google 技术讲座非常精彩,它是我得出示例的基础。 http://www.youtube.com/watch?v=XcT4yYu_TTs
Dependency Injection
Instead of instantiating the parts itself a car asks for the parts it needs to function.
Factory
Puts the pieces together to make a complete object and hides the concrete type from the caller.
Result
As you can see, Factories and DI complement each other.
Do you remember goldilocks and the three bears? Well, dependency injection is kind of like that. Here are three ways to do the same thing.
Example #1 - This is the worst because it completely hides the dependency. If you looked at the method as a black box you would have no idea it required a car.
Example #2 - This is a little better because now we know we need a car since we pass in a car factory. But this time we are passing too much since all the method actually needs is a car. We are passing in a factory just to build the car when the car could be built outside the method and passed in.
Example #3 - This is ideal because the method asks for exactly what it needs. Not too much or too little. I don't have to write a MockCarFactory just to create MockCars, I can pass the mock straight in. It is direct and the interface doesn't lie.
This Google Tech Talk by Misko Hevery is amazing and is the basis of what I derived my example from. http://www.youtube.com/watch?v=XcT4yYu_TTs
依赖注入(DI)和工厂模式相似的原因是它们是软件架构控制反转(IoC)的两种实现。 简而言之,它们是同一问题的两种解决方案。
因此,回答这个问题,工厂模式和 DI 之间的主要区别在于如何获取对象引用。 顾名思义,依赖注入会将引用注入或提供给您的代码。 使用工厂模式,您的代码必须请求引用,以便您的代码获取对象。 两种实现都删除或解耦了代码与代码所使用的对象引用的底层类或类型之间的链接。
值得注意的是,工厂模式(或者实际上是抽象工厂模式,即返回返回对象引用的新工厂的工厂)可以编写为动态选择或链接到运行时请求的对象的类型或类。 这使得它们与服务定位器模式非常相似(甚至比 DI 更相似),服务定位器模式是 IoC 的另一种实现。
工厂设计模式相当古老(就软件而言)并且已经存在了一段时间。 自从 IoC 架构模式最近流行以来,它正在复兴。
我想当谈到 IoC 设计模式时:注入器被注入,定位器被定位,工厂被重构。
The reason Dependency Injection (DI) and Factory Patterns are similar is because they are two implementations of Inversion of Control (IoC) which is a software architecture. Put simply they are two solutions to the same problem.
So to answer the question the main difference between the Factory pattern and DI is how the object reference is obtained. With dependency injection as the name implies the reference is injected or given to your code. With Factory pattern your code must request the reference so your code fetches the object. Both implementations remove or decouple the linkage between the code and the underlying class or type of the object reference being used by the code.
It's worth noting that Factory patterns (or indeed Abstract Factory patterns which are factories that return new factories that return object references) can be written to dynamically choose or link to the type or class of object being requested at run time. This makes them very similar (even more so than DI) to Service Locator pattern which is another implementation of the IoC.
The Factory design pattern is quite old (in terms of Software) and has been around for a while. Since the recent popularity of the architectural pattern IoC it is having a resurgence.
I guess when it comes to IoC design patterns: injectors be injecting, locators be locating and the factories have been refactored.
有些问题通过依赖注入很容易解决,但通过一套工厂却不容易解决。
一方面,控制反转和依赖注入 (IOC/DI) 与另一方面,服务定位器或一套工厂 (factory) 之间的一些区别是:
IOC/DI 是一个完整的域对象和服务本身的生态系统。 它按照您指定的方式为您设置一切。 您的域对象和服务是由容器构造的,而不是自行构造:因此它们对容器或任何工厂没有任何依赖关系。 IOC/DI 允许极高程度的可配置性,所有配置都位于应用程序最顶层(GUI、Web 前端)的一个位置(容器的构造)。
工厂抽象了领域对象和服务的一些构造。 但领域对象和服务仍然负责弄清楚如何构建自身以及如何获取它们所依赖的所有内容。 所有这些“活动”依赖项都会过滤应用程序中的所有层。 没有一个地方可以配置所有内容。
There are problems which are easy to solve with dependency injection which are not so easily solved with a suite of factories.
Some of the difference between, on the one hand, inversion of control and dependency injection (IOC/DI), and, on the other hand, a service locator or a suite of factories (factory), is:
IOC/DI is a complete ecosystem of domain objects and services in and of itself. It sets everything up for you in the way you specify. Your domain objects and services are constructed by the container, and do not construct themselves: they therefore do not have any dependencies on the container or on any factories. IOC/DI permits an extremely high degree of configurability, with all the configuration in a single place (construction of the container) at the topmost layer of your application (the GUI, the Web front-end).
Factory abstracts away some of the construction of your domain objects and services. But domain objects and services are still responsible for figuring out how to construct themselves and how to get all the things they depend on. All these "active" dependencies filter all the way through all the layers in your application. There is no single place to go to configure everything.