依赖注入应用 IoC 原则,确保类从不负责创建或提供它们自己的依赖项(因此也不负责这些依赖项的生命周期)。
However, 返回依赖注入页面【强】 IoC 不够强译者: - indeed, IoC as a principle has nothing particularly to do with dependencies or dependency injection per-se; Dependency Injection is a design pattern based around the principle of IoC.
IoC 可以在许多其他上下文中看到,包括那些与对象创建或依赖关系完全无关的上下文,例如通过 Mediator 或消息泵传递消息以触发事件处理程序。IoC 的其他(不相关的)例子包括:
使用事件处理函数/方法处理鼠标/键盘输入事件的窗口应用程序。
使用 Controller Actions 处理 HTTP 请求的 MVC web 应用程序。
(更新自原答案,作为对 IoC 的单独解释)
依赖注入模式
依赖注入是一种应用 IoC 原则的设计模式,以确保类在其构造函数或实例变量所使用的对象的创建或生存期中完全没有参与或意识到——对对象创建和实例变量填充的“常见”关注被推迟到框架中。
// Example without Dependency Injection...
class Foo {
constructor() {
// a 'Meow' instance is created within the Foo constructor
this.fred = new Meow();
// a service locator gets a 'WoofFactory' which in-turn
// is responsible for creating a 'Woof' instance.
// This demonstrates IoC but not Dependency Injection.
var factory = TheServiceLocator.GetWoofFactory();
this.barney = factory.CreateWoof();
}
}
因此,依赖注入只是意味着一个类推迟了 责任获取或提供它自己的依赖项,而这个责任属于任何想要创建一个实例的东西。(通常是 IoC 容器)
依赖反转原则
Dependency Inversion is broadly about de-coupling concrete classes by preventing those classes having any direct reference to each other.
注意: 依赖性反转在静态类型的编程语言(如 C # 或 Java)中通常更加明确,因为这些语言对变量名强制执行严格的类型检查。另一方面,依赖性反转已经在 Python 或 JavaScript 等动态语言中被动可用,因为这些语言中的变量没有任何特定的类型限制。
考虑静态类型语言中的一个场景,其中一个类需要从应用程序的数据库中读取记录的能力:
// class Foo depends upon a concrete class called SqlRecordReader.
class Foo {
reader: SqlRecordReader;
constructor(sqlReader: SqlRecordReader) {
this.reader = sqlReader;
}
doSomething() {
var records = this.reader.readAll();
// etc.
}
}
In this last example, Foo也许吧 receive a SqlRecordReader, or maybe a SoapRecordReader, or perhaps a FileRecordReader, or maybe even for unit testing a MockRecordReader - the point is that it doesn't know or care anything about different possible implementations of IRecordReader - provided of course those implementations live up to the Liskov代换原则.