DI(依赖注入)和IoC(反转控制)
依赖注入(Dependency Injection,简称DI)是一种设计模式,用于实现反转控制(Inversion of Control,简称IoC),其中一个类所依赖的对象由外部提供,而不是在类内部创建。
概念解释:
- 反转控制(Inversion of Control,IoC):是一种设计原则,用于减少代码之间的耦合度。通过反转控制,程序中的依赖关系由框架或容器来管理,而不是在程序内部直接控制。
- 依赖注入(Dependency Injection,DI):是实现IoC的一种方式,即一个类所依赖的对象由外部提供,而不是在类内部创建。
具体例子:
- A需要B:类A依赖于类B来完成其功能。
- 系统会自动把B注入到A中:系统会自动将类B的实例传递给类A,而不是让A自己创建或查找B的实例。
优点:
- 降低耦合度:类A与类B之间的耦合度降低,因为类A不需要直接依赖类B的实现。A只需要知道B的接口或者抽象类型,具体的实现由外部提供。
- 隐藏产品创建细节:类A不需要关心类B的创建细节,这样可以使类A更专注于其核心功能。具体的依赖对象如何创建、配置、初始化等细节被隐藏起来,由容器或者外部代码来处理。
场景:
想象在家里煮饭(类A),需要一口锅(类B)。如果必须自己去买锅、检查锅的质量,还要自己带回家(自己创建或获取依赖),这就有点麻烦,对吧?
依赖注入怎么做?
依赖注入就像是有一个好朋友(依赖注入框架),每次要煮饭时,只需要告诉他需要一口锅。他会帮找到并送到手上。只需要专心煮饭,不用管锅的来源和质量问题。
具体说明:
- 降低耦合度:煮饭的(类A)和锅(类B)之间的关系被弱化了,只需要知道有锅就行,不需要知道锅是怎么来的。这使得以后如果想换一种锅,或者需要其他厨房用品时,只需要告诉朋友就行,的煮饭逻辑完全不需要改动。
- 隐藏产品创建细节:不需要知道锅是在哪里买的、怎么挑选的,只需要知道朋友会把适合的锅给就行了。
举个编程例子:
-
没有依赖注入的情况:
public class Cooking { private Pot pot; public Cooking() { this.pot = new Pot(); // 自己去创建锅 } public void cook() { // 煮饭逻辑 } }
-
使用依赖注入的情况:
public class Cooking { private Pot pot; public Cooking(Pot pot) { this.pot = pot; // 锅由外部提供 } public void cook() { // 煮饭逻辑 } } // 外部代码 Pot pot = new Pot(); Cooking cooking = new Cooking(pot);
在第二种情况下,Cooking
类不再负责创建锅,锅是从外部传递进来的。这就是依赖注入的基本思想:把对象的创建和依赖关系的管理交给外部,让类只关注自己的核心功能。