引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。
曾经有人告诉我,你如何使用它才会有所不同!
我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。
谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?
引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。
曾经有人告诉我,你如何使用它才会有所不同!
我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。
谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?
我建议保持概念的简单明了。依赖注入更像是一种松散耦合软件组件的体系结构模式。工厂模式只是将创建其他类的对象的职责分离给另一个实体的一种方法。工厂模式可以被称为实现依赖注入的工具。依赖注入可以通过多种方式实现,比如使用构造函数进行依赖注入,使用映射xml文件等。
使用依赖注入框架,开发人员不需要手动准备和设置类实例的依赖项,这一切都是事先准备好的。
对于工厂,开发人员必须手工完成,并使用这些依赖对象创建类实例。
区别主要在于这一行中调用工厂并获取构造的对象,以及编写工厂方法来创建和设置所有内容(尽管可以认为,在依赖注入框架中,通过连接和配置对象关系,这也必须在一定程度上完成)。
如果是工厂,你就得打电话给任何需要这种东西的工厂。 使用依赖注入框架,你可以在类实例创建时依赖对象的存在。
我的观点是,工厂方法更静态,因为它的实现相当固定,而依赖注入框架更动态,因为类实例的实际组合更容易改变(例如。为了测试目的)在运行时。
我相信DI是工厂的一种抽象层,但是它们还提供了抽象之外的好处。真正的工厂知道如何实例化单一类型并配置它。好的DI层通过配置提供实例化和配置多种类型的能力。
显然,对于具有一些简单类型的项目(在其构造中需要相对稳定的业务逻辑),工厂模式易于理解、实现并且工作良好。
OTOH,如果您有一个包含许多类型的项目,您希望经常更改这些类型的实现,DI通过其配置为您提供了在运行时执行此操作的灵活性,而无需重新编译工厂。
有些问题用依赖注入很容易解决,而用一套工厂就不那么容易解决了。
一方面,控制反转和依赖注入(IOC/DI)与另一方面,服务定位器或工厂套件(factory)之间的一些区别是:
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).
工厂抽象了域对象和服务的一些构造。但是领域对象和服务仍然负责弄清楚如何构造自己,以及如何获得它们所依赖的所有东西。所有这些“活动的”依赖项都会在应用程序的所有层中进行筛选。没有一个地方可以配置所有的东西。
我相信DI是一种配置或即时化bean的方法。DI可以通过很多方式来实现,比如构造函数,setter-getter等等。
工厂模式只是实例化bean的另一种方式。此模式将主要用于必须使用工厂设计模式创建对象时,因为在使用此模式时,您不配置bean的属性,只实例化对象。
检查这个链接:依赖注入
比诺,
我不认为你必须选择其中一个而不是另一个。
将依赖类或接口移动到类构造函数或setter的行为遵循DI模式。传递给构造函数或集合的对象可以用Factory实现。
什么时候使用?使用开发人员擅长的模式。他们觉得什么最舒服,什么最容易理解。
Life cycle management is one of the responsibilities dependency containers assume in addition to instantiation and injection. The fact that the container sometimes keep a reference to the components after instantiation is the reason it is called a "container", and not a factory. Dependency injection containers usually only keep a reference to objects it needs to manage life cycles for, or that are reused for future injections, like singletons or flyweights. When configured to create new instances of some components for each call to the container, the container usually just forgets about the created object.
来自:http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html
当我读到关于DI的文章时,我也有同样的问题。 最后,这就是我所理解的,但如果我错了,请纠正我。
“很久以前,有一些小国,它们有自己的管理机构,根据自己的成文规则进行控制和决策。后来形成了一个大政府,消除了所有这些小的管理机构,这些机构只有一套规则(宪法),并通过法院执行。”
小王国的管理机构是“工厂”
大政府是“依赖注入器”。
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不是工厂模式的选择。使用工厂,我们可以很容易地从对象创建中封装随机算法,它支持一种称为“封装变化”的设计模式。
我知道这个问题很老了,但我想补充一下我的观点,
我认为依赖注入(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!!
不管怎样,评论区是开放的,你可以杀了我。
依赖注入
而不是实例化部件本身,汽车要求它的功能所需的部件。
class Car
{
private Engine engine;
private SteeringWheel wheel;
private Tires tires;
public Car(Engine engine, SteeringWheel wheel, Tires tires)
{
this.engine = engine;
this.wheel = wheel;
this.tires = tires;
}
}
工厂
将各个部分组合在一起以形成一个完整的对象,并对调用者隐藏具体类型。
static class CarFactory
{
public ICar BuildCar()
{
Engine engine = new Engine();
SteeringWheel steeringWheel = new SteeringWheel();
Tires tires = new Tires();
ICar car = new RaceCar(engine, steeringWheel, tires);
return car;
}
}
结果
正如你所看到的,工厂和DI是相辅相成的。
static void Main()
{
ICar car = CarFactory.BuildCar();
// use car
}
你还记得金发姑娘和三只熊吗?依赖注入有点像这样。这里有三种方法来做同样的事情。
void RaceCar() // example #1
{
ICar car = CarFactory.BuildCar();
car.Race();
}
void RaceCar(ICarFactory carFactory) // example #2
{
ICar car = carFactory.BuildCar();
car.Race();
}
void RaceCar(ICar car) // example #3
{
car.Race();
}
例#1——这是最糟糕的,因为它完全隐藏了依赖关系。如果你把这个方法看作一个黑盒子,你就不会知道它需要一辆车。
例2——这样会好一点,因为我们经过了一家汽车厂,现在我们知道我们需要一辆车。但是这次我们传递的太多了,因为这个方法实际上只需要一个car。我们正在路过一个工厂,只是为了建造汽车,当汽车可以在外面建造的方法和通过。
示例#3—这是理想的,因为该方法要求的正是它所需要的。不要太多也不要太少。我不需要为了创建MockCars而编写MockCarFactory,我可以直接传入mock。它是直接的,界面不会说谎。
Misko Hevery的谷歌技术演讲非常棒,这是我得到我的例子的基础。http://www.youtube.com/watch?v=XcT4yYu_TTs
注入框架是工厂模式的实现。
这完全取决于你的要求。如果您需要在应用程序中实现工厂模式,那么您的需求极有可能由众多注入框架实现中的一个来满足。
只有在任何第三方框架都不能满足您的需求时,您才应该推出自己的解决方案。编写的代码越多,需要维护的代码就越多。代码是一种负债而不是资产。
关于应该使用哪个实现的争论没有理解应用程序的体系结构需求那么重要。
依赖注入(DI)和工厂模式相似的原因是它们是控制反转(IoC)的两种实现,IoC是一种软件架构。简单地说,它们是同一问题的两种解决方案。
因此,为了回答这个问题,工厂模式和依赖注入模式之间的主要区别在于如何获得对象引用。依赖项注入顾名思义就是将引用注入或提供给您的代码。使用工厂模式,您的代码必须请求引用,以便您的代码获取对象。这两种实现都删除或解耦了代码与所使用的对象引用的底层类或类型之间的链接。
值得注意的是,工厂模式(或者实际上是抽象工厂模式,即返回返回对象引用的新工厂的工厂)可以被编写为在运行时动态地选择或链接到被请求的对象类型或类。这使得它们与服务定位器模式非常相似(甚至比DI更相似),后者是IoC的另一个实现。
工厂设计模式相当古老(就软件而言),并且已经存在了一段时间。由于IoC体系结构模式最近的流行,它正在复苏。
我想当涉及到IoC设计模式时:注入器被注入,定位器被定位,工厂被重构。
工厂设计模式
工厂设计模式的特点是
一个接口 实现类 一个工厂
当你这样问自己时,你可以观察到一些事情
工厂什么时候为实现类创建对象——运行时还是编译时? 如果您想在运行时切换实现,该怎么办?-不可能
这些是由依赖注入处理的。
依赖注入
您可以使用不同的方式注入依赖项。为了简单起见,让我们使用接口注入
在DI中,容器创建所需的实例,并将它们“注入”到对象中。
这样就消除了静态实例化。
例子:
public class MyClass{
MyInterface find= null;
//Constructor- During the object instantiation
public MyClass(MyInterface myInterface ) {
find = myInterface ;
}
public void myMethod(){
find.doSomething();
}
}
在我看来,使用依赖注入更好,如果你是: 1. 将代码部署在小分区中,因为它可以很好地解耦一个大代码。 2. 可测试性是DI可以使用的情况之一,因为你可以很容易地模拟非去耦的对象。通过使用接口,您可以轻松地模拟和测试每个对象。 3.你可以同时修改程序的每一部分,而不需要编码它的另一部分,因为它是松散解耦的。
您可以在这个链接中查看两种(和其他)方法在实际示例中的比较。
基本上,当需求发生变化时,如果您使用工厂而不是DI,您最终会修改更多的代码。
这对于手动DI也是有效的(例如,当没有外部框架为你的对象提供依赖关系,但你在每个构造函数中传递它们时)。
从表面上看,他们是一样的
简单来说,工厂模式,创建模式帮助我们创建一个对象——“定义一个创建对象的接口”。如果我们有一个键值类型的对象池(例如Dictionary),将键传递给工厂(我指的是简单工厂模式),您可以解析类型。完成工作! 另一方面,依赖注入框架(如结构图、Ninject、Unity等)似乎也在做同样的事情。
但是…“不要白费力气”
从架构的角度来看,这是一个绑定层,“不要白费力气”。
对于企业级应用程序,依赖注入的概念更像是一个定义依赖关系的体系结构层。为了进一步简化,您可以将其视为一个单独的类库项目,它进行依赖解析。主应用程序依赖于这个项目,其中依赖项解析器引用其他具体实现和依赖项解析。
除了来自Factory的“GetType/Create”之外,我们通常还需要更多的特性(使用XML定义依赖关系、模拟和单元测试等)。既然您引用了结构图,那么请查看结构图特性列表。这显然不仅仅是解决简单的对象映射。别白费力气了!
如果你只有一把锤子,那么所有东西看起来都像钉子
根据您的需求和您构建的应用程序类型,您需要做出选择。如果它只有很少的项目(可能是一个或两个..)并且涉及很少的依赖项,您可以选择一个更简单的方法。这就像使用ADO . net数据访问而不是使用实体框架进行简单的1或2个数据库调用,在这种情况下引入EF是多余的。
但是对于一个更大的项目,或者如果你的项目变得更大,我强烈建议有一个带有框架的DI层,并留出空间来改变你使用的DI框架(在主应用程序中使用Facade (Web应用程序,Web Api, Desktop..等)。
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.
尽管工厂可能适用于小型应用程序,但大型应用程序最好选择DI而不是工厂。
理论
这里有两点需要考虑:
谁创建对象:
[Factory]:你必须写如何创建对象。您有独立的Factory类,其中包含创建逻辑。 [依赖注入]:在实际情况下,这是由外部框架完成的(例如在Java中是spring/ejb/guice)。注入“神奇地”发生,无需显式地创建新对象。
它管理的对象类型:
[Factory]:通常负责有状态对象的创建 [依赖注入]:更可能创建无状态对象
关于如何在一个项目中同时使用工厂注入和依赖注入的实例
我们想要建造什么
用于创建包含多个名为orderline的条目的订单的应用程序模块。
体系结构
让我们假设我们想要创建以下分层架构:
域对象可以是存储在数据库中的对象。 存储库(DAO)帮助从数据库检索对象。 服务为其他模块提供API。允许对订单模块进行操作。
域层和工厂的使用
数据库中的实体是Order和OrderLine。Order可以有多个orderline。
现在是重要的设计部分。这个模块之外的模块是否应该自己创建和管理orderline ?不。只有当订单与之关联时,订单行才应该存在。最好能将内部实现隐藏到外部类。
但是如何在不了解OrderLines的情况下创建Order呢?
工厂
想要创建新订单的人使用了OrderFactory(它将隐藏关于我们如何创建订单的细节)。
这就是它在IDE中的样子。域包外部的类将使用OrderFactory而不是Order内部的构造函数。
依赖注入 依赖注入更常用于无状态层,如存储库和服务。
OrderRepository和OrderService由依赖注入框架管理。 存储库负责管理数据库上的CRUD操作。Service注入存储库并使用它来保存/查找正确的域类。
这里的大多数答案都解释了两者的概念差异和实现细节。但是我无法解释在应用上的差异,IMO是最重要的,OP问的是什么。所以让我重新讨论这个话题……
曾经有人告诉我,你如何使用它才会有所不同!
完全正确。在90%的情况下,你可以使用Factory或DI来获取对象引用,通常你最终会使用后者。在另外10%的情况下,使用Factory是唯一正确的方法。这些情况包括通过运行时参数的变量获取对象。是这样的:
IWebClient client = factoryWithCache.GetWebClient(url: "stackoverflow.com",
useCookies: false, connectionTimeout: 120);
在这种情况下,从DI获取客户端是不可能的(或者至少需要一些丑陋的解决方案)。因此,作为决策的一般规则:如果可以在没有任何运行时计算参数的情况下获得依赖项,则首选DI,否则使用Factory。
如果传递的参数可以在工厂中分组,那么它也是构造函数过度注入的一个很好的解决方案,看看下面的代码*):
public AddressModelFactory(IAddressAttributeService addressAttributeService,
IAddressAttributeParser addressAttributeParser,
ILocalizationService localizationService,
IStateProvinceService stateProvinceService,
IAddressAttributeFormatter addressAttributeFormatter)
{
this._addressAttributeService = addressAttributeService;
this._addressAttributeParser = addressAttributeParser;
this._localizationService = localizationService;
this._stateProvinceService = stateProvinceService;
this._addressAttributeFormatter = addressAttributeFormatter;
}
看看构造函数,你只需要在那里传递IAddressModelFactory,所以参数更少*):
public CustomerController(IAddressModelFactory addressModelFactory,
ICustomerModelFactory customerModelFactory,
IAuthenticationService authenticationService,
DateTimeSettings dateTimeSettings,
TaxSettings taxSettings,
ILocalizationService localizationService,
IWorkContext workContext,
IStoreContext storeContext,
ICustomerService customerService,
ICustomerAttributeParser customerAttributeParser,
ICustomerAttributeService customerAttributeService,
IGenericAttributeService genericAttributeService,
ICustomerRegistrationService customerRegistrationService,
ITaxService taxService,
CustomerSettings customerSettings,
AddressSettings addressSettings,...
你可以看到在CustomerController中传递了很多参数,是的,你可以看到这是构造函数的过度注入,但这就是DI的工作方式。CustomerController没有任何问题。
*)代码来自nopCommerce。
简单来说,依赖注入和工厂方法分别意味着推和拉机制。
拉机制:类间接依赖于工厂方法,工厂方法又依赖于具体类。
推送机制:根组件可以在一个位置配置所有依赖组件,从而促进高维护和松耦合。
使用Factory方法时,创建新对象的责任仍然由类承担(尽管是间接的),而使用依赖注入时,责任是外包的(尽管是以泄露抽象为代价)。
我认为它们是正交的,可以一起使用。让我给你看一个我最近在工作中遇到的例子:
我们使用Java中的Spring框架进行DI。一个单例类(Parent)必须实例化另一个类(Child)的新对象,这些对象有复杂的协作者:
@Component
class Parent {
// ...
@Autowired
Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) {
this.dep1 = dep1;
this.dep2 = dep2;
}
void method(int p) {
Child c = new Child(dep1, dep2, ..., depN, p);
// ...
}
}
在这个例子中,Parent必须接收DepX实例,并将它们传递给Child构造函数。问题在于:
Parent对Child的了解比它应该了解的要多 母公司的合作者太多了 向Child添加依赖项需要更改Parent
这时我意识到工厂非常适合这里:
它隐藏了Child类的所有真实参数,就像Parent所看到的那样 它封装了创建子节点的知识,这些知识可以集中在DI配置中。
这是简化的Parent类和ChildFactory类:
@Component
class Parent {
// ...
@Autowired
Parent(ChildFactory childFactory) {
this.childFactory = childFactory;
}
void method(int p) {
Child c = childFactory.newChild(p);
// ...
}
}
@Component
class ChildFactory {
// ...
@Autowired
Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) {
this.dep1 = dep1;
this.dep2 = dep2;
// ...
this.depN = depN;
}
Child newChild(int p) {
return new Child(dep1, dep2, ..., depN, p);
}
}
我使用这两种方法来创建反转控制策略,为在我之后需要维护它的开发人员提供了更强的可读性。
我使用工厂来创建不同的层对象(业务,数据访问)。
ICarBusiness carBusiness = BusinessFactory.CreateCarBusiness();
另一个开发人员会看到这一点,当创建业务层对象时,他会在BusinessFactory中查看,智能感知会为开发人员提供所有可能创建的业务层。不需要玩游戏,找到我想要创建的界面。
这个结构已经是控制反转了。我不再负责创建特定的对象。但是您仍然需要确保依赖注入能够轻松地更改内容。 创建自己的自定义依赖注入是荒谬的,所以我使用Unity。在CreateCarBusiness()中,我要求Unity解决哪个类属于这个和它的生命周期。
所以我的代码工厂依赖注入结构是:
public static class BusinessFactory
{
public static ICarBusiness CreateCarBusiness()
{
return Container.Resolve<ICarBusiness>();
}
}
现在我两者兼得。我的代码对于其他开发人员来说也更易于阅读,因为我使用的对象的范围,而不是构造函数依赖注入,它只是说在创建类时每个对象都是可用的。
当我创建单元测试时,我使用它将我的数据库数据访问更改为自定义编码的数据访问层。我不希望我的单元测试与数据库、网络服务器、电子邮件服务器等通信。他们需要测试我的业务层,因为这是智能所在。
DI为您提供了一个组合根,这是连接对象图的一个集中位置。这往往使对象依赖关系非常显式,因为对象确切地要求它们所需要的东西,并且只有一个地方可以得到它。
组合根是一种清晰而直接的关注点分离。被注入的对象应该不依赖于DI机制,无论是第三方容器还是DIY DI。DI应该是不可见的。
工厂往往更加分散。不同的对象使用不同的工厂,工厂表示对象与其实际依赖关系之间的额外间接层。这个附加层将自己的依赖项添加到对象图中。工厂不是看不见的。工厂是一个中间商。
因此,更新工厂的问题更大:因为工厂是业务逻辑的依赖项,修改它们可能会产生连锁反应。组合根不是业务逻辑的依赖项,因此可以单独修改它。
GoF提到了更新抽象工厂的困难。他们的部分解释被引用在这里的回答中。将DI与工厂进行对比也与ServiceLocator是否是反模式这个问题有很多相似之处。
最终,选择哪个答案可能是固执己见的;但我认为这可以归结为一个工厂是一个中间人。问题在于,除了提供产品之外,这个中间商是否还能通过增加额外价值来发挥自己的作用。因为如果你能在没有中间商的情况下得到同样的产品,那为什么不把中间商去掉呢?
一个图表有助于说明其中的区别。
[Factory] ->有一个基于请求参数创建类的类。毕竟,“工厂”在现实世界中也为你制造“物品”。你可以让你的汽车供应商工厂生产(免费:)特斯拉。1给你。
[DI] ->一个(服务)容器,用于存储接口(压缩类)。你不关心创建对象。你只需要让某个人/某个地方实现它,细节和其他东西对你、调用者或消费者都不重要。
DI是SOLID原则中“D”的基础。