Bin*_*ony 484 design-patterns dependency-injection factory-pattern
引用依赖注入的大多数示例,我们也可以使用工厂模式解决.看起来在使用/设计时,依赖注入和工厂之间的差异是模糊的还是薄的.
一旦有人告诉我你如何使用它会有所作为!
我曾经使用StructureMap一个DI容器来解决问题,后来我重新设计它以使用一个简单的工厂并删除了对StructureMap的引用.
任何人都可以告诉我他们之间的区别是什么,在哪里使用什么,这里最好的做法是什么?
wil*_*ood 285
使用工厂时,您的代码仍然负责创建对象.通过DI,您将该职责外包给另一个类或框架,该框架与您的代码分开.
Per*_*der 215
我建议保持概念简单明了.依赖注入更像是松散耦合软件组件的架构模式.工厂模式只是将创建其他类对象的责任分离到另一个实体的一种方法.工厂模式可以被称为实现DI的工具.依赖注入可以通过许多方式实现,例如DI使用构造函数,使用映射xml文件等.
Des*_*tar 177
依赖注入
汽车不是要实例化部件本身,而是要求它运行所需的部件.
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;
}
}
Run Code Online (Sandbox Code Playgroud)
厂
将碎片放在一起以制作完整的物体并隐藏来自呼叫者的具体类型.
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;
}
}
Run Code Online (Sandbox Code Playgroud)
结果
如您所见,工厂和DI相互补充.
static void Main()
{
ICar car = CarFactory.BuildCar();
// use car
}
Run Code Online (Sandbox Code Playgroud)
你还记得金发姑娘和三只熊吗?那么,依赖注入有点像那样.这有三种方法可以做同样的事情.
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();
}
Run Code Online (Sandbox Code Playgroud)
示例#1 - 这是最糟糕的,因为它完全隐藏了依赖性.如果你把方法视为一个黑盒子,你根本不知道它需要一辆车.
示例#2 - 这有点好,因为现在我们知道自从我们进入汽车工厂以来我们需要一辆汽车.但这次我们传球太多,因为所有方法实际需要的都是汽车.当汽车可以在方法之外建造并通过时,我们正在通过一个工厂来建造汽车.
示例#3 - 这是理想的,因为该方法准确询问它需要什么.不是太多或太少.我不必为了创建MockCars而编写MockCarFactory,我可以直接传递模拟.它是直接的,界面不会说谎.
Misko Hevery的Google Tech Talk非常棒,是我从中得到的例子的基础.http://www.youtube.com/watch?v=XcT4yYu_TTs
Tom*_*her 45
依赖注入(DI)和工厂模式相似的原因是因为它们是控制反转(IoC)的两种实现,它是一种软件体系结构.简而言之,它们是同一问题的两种解决方案.
因此,为了回答这个问题,工厂模式和DI之间的主要区别在于如何获得对象引用.使用依赖注入意味着引用被注入或提供给您的代码.使用Factory模式,您的代码必须请求引用,以便您的代码获取对象.两种实现都删除或解耦代码与代码使用的对象引用的基础类或类型之间的链接.
值得注意的是,工厂模式(或实际上是工厂返回返回对象引用的新工厂的抽象工厂模式)可以编写为动态选择或链接到运行时请求的对象的类型或类.这使得它们与服务定位器模式非常相似(甚至比DI更多),这是IoC的另一种实现.
工厂设计模式相当陈旧(就软件而言)并且已经存在了一段时间.自从最近建筑模式IoC的普及以来,它正在复苏.
我想当谈到IoC设计模式时:注入器是注入的,定位器是定位的,工厂已经被重构.
yfe*_*lum 40
存在易于通过依赖注入解决的问题,这些问题不是通过一组工厂很容易解决的.
一方面,控制和依赖注入(IOC/DI)的反转,另一方面,服务定位器或一组工厂(工厂)之间的一些区别是:
IOC/DI是一个完整的域对象和服务生态系统.它以您指定的方式为您设置所有内容.您的域对象和服务由容器构造,并且不构造自身:因此它们对容器或任何工厂没有任何依赖性.IOC/DI允许极高的可配置性,所有配置都在一个位置(容器的构造)位于应用程序的最顶层(GUI,Web前端).
工厂抽象出域域对象和服务的一些构造.但是域对象和服务仍然负责确定如何构建自己以及如何获得他们所依赖的所有东西.所有这些"活动"依赖项都会过滤应用程序中的所有层.没有一个地方可以配置一切.
小智 25
DI的一个缺点是它不能用逻辑初始化对象.例如,当我需要创建一个具有随机名称和年龄的角色时,DI不是工厂模式的选择.通过工厂,我们可以轻松地从对象创建中封装随机算法,该算法支持称为"封装变化的内容"的设计模式之一.
Pup*_*Pup 22
生命周期管理是依赖性容器除了实例化和注入之外所承担的责任之一.容器有时在实例化后保留对组件的引用这一事实是它被称为"容器"而不是工厂的原因.依赖注入容器通常只保留对管理生命周期所需的对象的引用,或者为将来注入而重用的对象,如单例或flyweights.当配置为每次调用容器创建一些组件的新实例时,容器通常只会忘记创建的对象.
来自:http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html
小智 16
我相信DI是工厂的一种抽象层,但它们也提供了超越抽象的好处.真正的工厂知道如何实例化单个类型并对其进行配置.良好的DI层通过配置提供实例化和配置多种类型的能力.
显然,对于具有一些简单类型的项目,在构造中需要相对稳定的业务逻辑,工厂模式易于理解,实现并且运行良好.
OTOH,如果你有一个包含许多类型的项目,你希望它们的实现经常发生变化,那么DI通过它的配置为你提供了灵活性,可以在运行时完成,而无需重新编译你的工厂.
Mar*_*zak 14
有两个要点需要考虑:
谁创造了对象
它管理什么样的对象:
用于创建订单的应用程序模块,其中包含多个称为订单行
我们假设我们要创建以下层架构:
域对象可以是存储在数据库内的对象.存储库(DAO)帮助从数据库中检索对象.Service为其他模块提供API.在order模块上操作
将在数据库中的实体是Order和OrderLine.订单可以有多个OrderLines.

现在是重要的设计部分.这个模块之外的模块是否应该自己创建和管理OrderLines?编号订单行只有在与订单关联时才存在.如果你可以将内部实现隐藏到外部类中,那将是最好的.
但是如何在不了解OrderLines的情况下创建Order?
厂
想要创建新订单的人使用OrderFactory(它将隐藏有关我们如何创建Order的详细信息).
这就是IDE内部的样子.domain包外的类将使用OrderFactory而不是内部的构造函数Order
OrderRepository和OrderService由依赖注入框架管理.存储库负责管理数据库上的CRUD操作.Service注入Repository并使用它来保存/查找正确的域类.
Fra*_*ana 12
我知道这个问题已经过时但我想补充五美分,
我认为依赖注入(DI)在很多方面都像可配置的工厂模式(FP),从这个意义上来说,你可以用DI做的任何东西都可以用这样的工厂来完成.
实际上,如果您使用spring,例如,您可以选择自动装配资源(DI)或执行以下操作:
MyBean mb = ctx.getBean("myBean");
Run Code Online (Sandbox Code Playgroud)
然后使用'mb'实例做任何事情.这不是一个工厂的调用会返回你的实例?
我注意到大多数FP示例之间唯一真正的区别是你可以在xml或另一个类中配置"myBean",并且框架将作为工厂工作,但除此之外是同样的事情,并且你肯定有一个工厂可以读取配置文件或获得所需的实现.
如果你问我的意见(而且我知道你没有),我相信DI会做同样的事情但只会增加开发的复杂性,为什么呢?
好吧,首先,要知道您使用DI自动装配的任何bean所使用的实现是什么,您必须转到配置本身.
但是......那个你不必知道你正在使用的对象的实现的承诺怎么样?pfft!当真?当你使用这样的方法时...你是不是写了实现?即使你不这样做,你几乎不是一直在看实现如何做它应该做的事情?
最后一点,DI框架承诺你将构建与它分离的东西,并没有依赖于它们的类,如果你正在使用一个框架,你构建了所有东西,如果你不得不改变方法或框架它不是一件容易的事......永远!...但是,既然你围绕那个特定的框架建立了一切,而不是担心什么是最适合你的业务的解决方案,那么在这样做时你将面临一个双向问题.
事实上,我可以看到FP或DI方法的唯一真正的业务应用程序是,如果您需要更改运行时使用的实现,但至少我知道的框架不允许您这样做,您必须离开在开发时配置完美的一切,如果您需要使用另一种方法.
所以,如果我有一个在同一个应用程序中的两个作用域中执行不同的类(比方说,两个持有的公司),我必须配置框架来创建两个不同的bean,并调整我的代码以使用它们.是不是就像我写这样的东西一样:
MyBean mb = MyBeanForEntreprise1(); //In the classes of the first enterprise
MyBean mb = MyBeanForEntreprise2(); //In the classes of the second enterprise
Run Code Online (Sandbox Code Playgroud)
与此相同:
@Autowired MyBean mbForEnterprise1; //In the classes of the first enterprise
@Autowired MyBean mbForEnterprise2; //In the classes of the second enterprise
Run Code Online (Sandbox Code Playgroud)
还有这个:
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
Run Code Online (Sandbox Code Playgroud)
在任何情况下,您都必须更改应用程序中的某些内容,无论是类还是配置文件,但您必须重新部署它.
做这样的事情不是很好吗:
MyBean mb = (MyBean)MyFactory.get("mb");
Run Code Online (Sandbox Code Playgroud)
这样,您可以设置工厂的代码,以便在运行时获得正确的实现,具体取决于已记录的用户企业?现在这会有所帮助.你可以添加一个带有新类的新jar,甚至可以在运行时设置规则(或者如果你打开这个选项就添加一个新的配置文件),不改变现有的类.这将是一个动态工厂!
对于每个企业必须编写两个配置,甚至可能每个企业都有两个不同的应用程序,这不会更有帮助吗?
你可以告诉我,我不需要在运行时进行切换,所以我配置了应用程序,如果我继承该类或使用其他实现,我只需更改配置并重新部署.好的,这也可以通过工厂完成.说实话,你这次做了多少次?也许只有当你的应用程序将在你公司的其他地方使用时,你才会将代码传递给另一个团队,他们会做这样的事情.但是,嘿,这也可以在工厂完成,并且在动态工厂中会更好!
无论如何,评论部分如果打开你就杀了我.
IOC是一个通过两种方式实现的概念.依赖项创建和依赖项注入,Factory/Abstract工厂是依赖项创建的示例.依赖注入是构造函数,设置器和接口.IOC的核心是不依赖于具体的类,而是定义方法的抽象(比如接口/抽象类)并使用该抽象来调用具体类的方法.像Factory模式一样返回基类或接口.Similariliy依赖注入使用基类/接口来设置对象的值.
通过依赖注入,客户端不需要自己获取它的依赖关系,它们都是事先准备好的.
对于工厂,有人必须调用这些工具将生成的对象转移到需要它们的地方.
差异主要在于这一行,它调用工厂并获取构造的对象.
但是对于工厂,你必须在需要这样一个对象的地方写下这一行.使用DI,您只需创建一次布线(使用和创建对象之间的关系),然后再依赖于对象的存在.另一方面,DI通常需要更多(在多大程度上取决于框架)在准备方面的工作.
| 归档时间: |
|
| 查看次数: |
155092 次 |
| 最近记录: |