依赖注入
撰写于 2019-07-03 修改于 2019-07-03 分类 Unity
依赖注入
最近在研究一个框架CatLib,里面核心思想就是依赖注入,那什么是依赖注入呢?其实思想很简单,目的也很明确-解耦。这种模式适合于组件开发!
什么是控制反转(IOC)
IOC的全称是Inversion of Control
,控制反转,意思就是:主动控制变为被动接受,举例:
- 非IOC: A控制着B,A控制着B的生命周期,创建、使用、销毁
- IOC: A接受B,A只有B的使用权,创建和销毁由第三方控制
那在IOC模式下,谁负责创建和销毁B呢?容器!
那在IOC模式下,B怎么把使用权给A呢,也就是B的实例怎么交给A呢?依赖注入!
什么是依赖注入(DI)
DI的全称是Dependency Injection
,依赖注入,其实按我的意思就是注入依赖,额,意思都差不多,为什么需要依赖注入呢,举个例子:
public interface Wheel
{
public void Scroll();
}
public class CarWheel: Wheel
{
private int color;
CarWheel(int color)
{
this.color = color;
}
Scroll()
{
Console.WriteLine("car wheel scroll!");
}
}
public class Car
{
//汽车轮子
private Wheel carWheel = new CarWheel(1);
Run()
{
Wheel.Scroll();
}
}
上面例子展示了 Car
依赖于 CarWheel
,什么是依赖呢?只要A类中用到了B类型,A就依赖于B。这种模式有什么坏处呢,耦合!比如说我现在需要在构造轮子时传入轮子的尺寸,那就要更改 Car
中CarWheel
的构造函数调用,传入尺寸,或者我不想用CarWheel
了,我想用另一个实现了Wheel
的类型,还是要改动 Car
这个类。从另一种抽象方式上来看,可以把Car
看成我们要构建的主系统,而Wheel
是系统中的plugin,主系统并不强依赖于任何一个插件,但一旦插件被加载,主系统就应该可以准确调用适当插件的功能。
其实不管是面向服务的编程模式,还是基于插件的框架式编程,为了实现松耦合(服务调用者和提供者之间的or框架和插件之间的),都需要在必要的位置实现面向接口编程,在此基础之上,还应该有一种方便的机制实现具体类型之间的运行时绑定,这就是DI所要解决的问题。
依赖注入的实现方式
先直观感受一下依赖注入和非依赖注入。
//非依赖注入
class Employee {
Address address;
Employee() {
address = new Address();
}
}
//依赖注入
class Employee {
Address address;
Employee(Address address) {
this.address=address;
}
}
上面就是依赖注入的一种方式:构造器注入,从上面可以看出,在依赖注入中,Employee
依赖的Address
实例由构造函数传入,Employee
不负责address
的构造,那谁负责Address
实例的构造呢?需要一个容器来完成!容器通过反射的方式,来构造Address
实例来注入到Employee
的构造函数里面,所以核心就是DI容器!
依赖注入的三种方式:
- 构造器注入
- 设值注入
- 接口注入
具体可参考深度理解依赖注入