我理解依赖注入是什么,但我仍然没有看到它对消费者有何益处的全貌。见下面的例子。
//bad
class car () {
var tire = new Tire('snow');
}
//good
class car () {
var tire;
constructor(tire){
this.tire=tire
}
}
所以我读过的大多数文章都说上面的例子很好,因为它消除了汽车对轮胎的依赖性,因此变得更加可测试。但是实例化汽车对象的另一个类怎么样呢。如果driver
类要召唤car
类,则不会强制驱动程序实例化car
对象和tires
。似乎依赖性总是得到进一步传播。这到底在哪里?什么实际实例化对象?这是DI框架的全部内容吗?
答案 0 :(得分:1)
你是正确的,依赖性要求一直“向上传播”。想要实例化他们的汽车的驾驶员需要携带Car
和Tire
。具有许多驱动程序的驱动程序池需要带有Driver
,Car
和Tire
等等等等。解决这个问题的简单方法是将东西捆绑到工厂中:
class Driver {
constructor(carFactory) {
this.car = carFactory.newCarWithRegularTires();
}
}
(仅供说明之用,见下文。)
您可以注入另一个可以创建其他汽车的工厂,Car
的依赖关系可以在Driver
不需要知道任何此类情况的情况下发生变化。
更进一步,您可以创建一个通用的全局工厂,它可以创建各种对象,并知道如何满足每个对象的依赖关系,这是一个依赖注入容器。您通常以文本格式配置它们,声明Car
需要Tire
,当您要求Car
实例时,它知道首先实例化Tire
传递它。
DI容器的缺点是,虽然您仍然可以通过重新配置DI容器来交换依赖关系,但这有时意味着您必须重新配置整个事物并且它成为一个巨大的相互依赖的对象注册表。你应该避免创建一个巨大的超级容器,但要保持模块化。
关于工厂的另一个词:上面的工厂例子不是很好。如果对象需要在运行时创建对象的新实例,则应使用工厂。它应该不使用工厂只是为了满足可以直接注入的依赖。
最后,您希望在直接声明和接收其依赖项的类之间取得平衡,但也不要创建极其深层的依赖层次结构。保持依赖关系尽可能浅是一个良好的开端,在stategic点引入工厂或模块化DI容器是另一种方式。