控制反转(英语:Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。实现控制反转主要有两种方式:依赖注入和依赖查找。两者的区别在于,前者是被动的接收对象,在类 A 的实例创建过程中即创建了依赖的 B 对象,通过类型或名称来判断将不同的对象注入到不同的属性中,而后者是主动索取相应类型的对象,获得依赖对象的时间也可以在代码中自由控制。

依赖注入

  • 基于接口。实现特定接口以供外部容器注入所依赖类型的对象。
  • 基于 set 方法。实现特定属性的 public set 方法,来让外部容器调用传入所依赖类型的对象。
  • 基于构造函数。实现特定参数的构造函数,在新建对象时传入所依赖类型的对象。

依赖查找

依赖查找更加主动,在需要的时候通过调用框架提供的方法来获取对象,获取时需要提供相关的配置文件路径、key 等信息来确定获取对象的状态。

控制和反转

什么是控制?又控制了什么?从接触面向对象以来,我们碰到的最多的问题就是解耦。对于一个程序来说,对象之间的耦合再正常不过,因此也诞生出了很多设计模式来解决这个问题。今天说的控制反转就是众多解决方法中比较流行的一种。控制,顾名思义就是对程序的处理流程,组成方式进行控制,这一切都是我们写程序的来决定的。为了解决一个问题,我们都是主动出击,需要什么就new什么,这过程中设计的一切细节都要我们亲自掌握。而Ioc的思想就是帮助我们把我们需要的对象(或者说资源)创建出来,我们在处理中需要什么,它都可以直接拿给我们来用。创建对象的,提供资源的主动权已经不再是我们,而是Ioc容器。所以,在这种设计思想下的程序中,Ioc容器是控制的一方,控制这整个程序的资源。那么反转也相应的更容易理解了,我们不再控制一切,专注于业务,从原来的完全掌控方,变为了资源的使用方,控制资源的事情都交了出去,实现了反转。

Ioc

如图所示,当程序启动时,将各种功能模块注册到IoC容器中,利用容器统一管理资源。业务逻辑(另一个对象)只需关注自己的实现,而不必再分心关注各个所需资源的创建,引用等。任务需要的资源,IoC容器都会自动注入到我们的逻辑中来。这个注入的过程也就是依赖注入。因此依赖注入是实现IoC的一种手段。

依赖注入

本教程也是ASP.NET Core的一个预备知识的介绍,因此下面将ASP.NET Core中的IoC相关代码展示出来,以供理解。

注册功能模块:

1
2
3
4
5
6
7
//Startup.cs
public void ConfigureServices(IServiceCollection services)
{
  ...
  services.AddScoped<IUserService,UserService>();
  ...
}

注入到业务逻辑中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
//AuthorizeController
[ApiController]
public class AuthorizeController: BaseController
{
  private readonly IUserService _userService;

  public AuthorizeController(IUserService userService)
  {
    _userService = userService;
  }
  ...
}

模块实现:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public interface IUserService
{
  string GetUserName(string userId);

  bool ValidatePassword(string userName, string password);
}

public class UserService:IUserService
{
  public string GetUserName(string userId)
  {
    return $"UserName:{userId}";
  }

  public bool ValidatePassword(string userName, string password)
  {
    if (userName == "xxxxxx" && password == "xxxxxxxxx")
    {
      return true;
    }

    return false;
  }
}

总结

  • 控制反转是一种在软件工程中解耦合的思想,调用类只依赖接口,而不依赖具体的实现类,减少了耦合。类与类之间的耦合关系在运行时由IoC容器建立。控制权交给了容器,在运行的时候由容器决定将具体的实现动态的注入到调用类的对象(业务逻辑)中。
  • 依赖注入是控制反转的一种实现方式。依赖注入就是将实例变量传入到一个对象(业务逻辑)中去。

(全文完)