依赖注入

撰写于 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。这种模式有什么坏处呢,耦合!比如说我现在需要在构造轮子时传入轮子的尺寸,那就要更改 CarCarWheel的构造函数调用,传入尺寸,或者我不想用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容器!

依赖注入的三种方式:

  1. 构造器注入
  2. 设值注入
  3. 接口注入

具体可参考深度理解依赖注入

Site by ZHJ using Hexo & Random

Hide