引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。
曾经有人告诉我,你如何使用它才会有所不同!
我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。
谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?
引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。
曾经有人告诉我,你如何使用它才会有所不同!
我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。
谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?
当前回答
依赖注入
而不是实例化部件本身,汽车要求它的功能所需的部件。
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是一种配置或即时化bean的方法。DI可以通过很多方式来实现,比如构造函数,setter-getter等等。
工厂模式只是实例化bean的另一种方式。此模式将主要用于必须使用工厂设计模式创建对象时,因为在使用此模式时,您不配置bean的属性,只实例化对象。
检查这个链接:依赖注入
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
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而不是工厂。
当使用工厂时,您的代码实际上仍然负责创建对象。通过DI,你可以将职责外包给另一个类或框架,这与你的代码是分开的。
使用依赖注入框架,开发人员不需要手动准备和设置类实例的依赖项,这一切都是事先准备好的。
对于工厂,开发人员必须手工完成,并使用这些依赖对象创建类实例。
区别主要在于这一行中调用工厂并获取构造的对象,以及编写工厂方法来创建和设置所有内容(尽管可以认为,在依赖注入框架中,通过连接和配置对象关系,这也必须在一定程度上完成)。
如果是工厂,你就得打电话给任何需要这种东西的工厂。 使用依赖注入框架,你可以在类实例创建时依赖对象的存在。
我的观点是,工厂方法更静态,因为它的实现相当固定,而依赖注入框架更动态,因为类实例的实际组合更容易改变(例如。为了测试目的)在运行时。