什么是依赖注入(DI)

1,790 阅读2分钟

本文将会对依赖注入做一个简单的介绍。

假如我们要从零开始做一个 to-B 方向的平台,最开始的想法是什么呢?

  1. 在前端蛮荒纪,什么都是从零开始,直接撸 html、js、css,所以现在是这样子的。

(管理员用户)意见反馈.png

  1. 渐渐的前端涌入了很多人,大家开发出很多好用的模块,再后来,Grunt、Browserify、gulp、webpack 等前端打包工具,npm、yarn 等包管理工具横空出世,我们渐渐地可以使用其他人开发出的模块去开发我们的网站,这就是广义的依赖注入

(管理员用户)意见反馈 (3).png

  1. 再到后来,前端涌入了更多的人,Angular、React、Vue 横空出世,我们开始采用框架来开发网站,但是我们不需要关心 React 里面用了什么模块、进行了什么处理,这就是广义上的控制反转

(管理员用户)意见反馈 (4).png

总的来说,前端的发展史就是一个面向对象语言的进化史呢。

众所周知,javascript 是一门面向对象(Object-oriented programming,OOP)的语言,依赖注入(DI)和控制反转(IoC)是具体的手段,是OOP理论中依赖倒置原则的体现形式,通过信息隐藏降低对象之间的耦合

将创建对象的任务转移给其他 class,并直接使用依赖项的过程,被称为“依赖项注入”。(DI)

IOC 就是一个可以自动实例化具体类并且管理各对象之间关系的容器,有了这个自动化的容器,我们关注的就不是具体的关系,而是上升到只需关注抽象之间的关系,而且还可以省去手动实例化。

事实上我们使用某些npm 的过程就是一种对依赖注入的使用了。再比如以下 jquery 的注入。

!(function ($, window) {
   ...
})(jQuery, window)

没有使用依赖注入示例模块

// team.js
var User = require('./user');

function getTeam(teamId) {
  return User.find({teamId: teamId});
}

module.exports.getTeam = getTeam;

使用依赖注入示例模块

// team.js
function Team(options) {
  this.options = options;
}

Team.prototype.getTeam = function(teamId) {
  return this.options.User.find({teamId: teamId})
}

function create(options) {
  return new Team(options);
}

或者尝试 es6 的写法

// team.js
class Team {
	constuctor(options) {
		this.options = options;
	}
	
	getTeam: (teamId) => {
  	return this.options.User.find({teamId: teamId})
	}
}

function create(options) {
  return new Team(options);
}

比较显示使用依赖注入的模块有:

import { Controller, Get } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  @Get()
  findAll(): string {
    return 'This action returns all cats';
  }
}

(该代码截取自 nest 官网)

或者是这样的代码:

import { Component } from '@angular/core';

@Component({
  selector: 'hello-world',
  template: `
    <h2>Hello World</h2>
    <p>This is my first component!</p>
    `,
})
export class HelloWorldComponent {
  // The code in this class drives the component's behavior.
}

(该代码截取自 Angular 官网)

学习了依赖注入后,我们可以更专注于模块的封装,从而更好的实现高内聚低耦合的代码。

image.png

更多

什么是IOC(控制反转)、DI(依赖注入)