浅谈我(前端)对AOP与IoC的理解

907 阅读4分钟

前言

最近呢,项目组准备推进做自己的 SDK 组件库,然后组长在开我们内部的评审会的时候讲到了这两个点。第一次听到的时候一脸懵逼,对前端小白的我来说又是一次升级,赶紧会后开始学习。接下来进入正题。

简介

百度百科 👇

  • AOP (面向切面编程)

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

  • IoC (控制反转) 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

我的理解 👇(如有错误还望指出)

  • AOP (面向切面编程)

切面就是将一个东西按功能切割成不同的几个面,每个面分别对应不同的点。最后再共同组成一个东西,就像积木,乐高一样。你可以对每一个面进行调整但不会影响到其他的面,每一个面又是独立的面负责单一的功能。

  • IoC (控制反转)

将自身模块所需要的依赖不直接引入自身,通过容器找到自身所需的依赖再从容器中获取。这样就不会让依赖与模块高度耦合在一起,类似于插件的形式。比如Vue是我所需要的依赖,将一些基于 Vue 开发的库比如 Element Ui 就是插件,我插件内不引入我的 Vue 依赖,后续使用的时候由 Vue 实例(容器传给我的插件)。

用处

AOP 到底有啥用呢?我们先来看一段代码。

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

用过 nestjs 的人应该都知道,这段代码就是初始化 nest 项目的模版代码。

在 nestjs 里面写路由直接就装饰器 @Get(path?) or @xxx(path?)

装饰器的部分只做路由的获取,我下面函数的部分只处理业务逻辑。

我想要获取query上的某个参数@Query('name')

可以看出nestjs写路由会非常的舒服,我们只管处理业务逻辑其他的用装饰取就好了。

然后 IoC 呢?

这边我们看到上面那段代码的 AppController 类的 constructor 中接收到 appService 参数,这个是啥呢,我们没有在代码里面引入,为什么能直接调用呢?

下面是 appService 的代码

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

可以看到我们的 AppService 类被 Injectable 了,这边就是将 AppService 注入到容器当中。

回顾刚刚 AppController 的代码的 constructor 的行参中有 appService 这个就是告诉容器,“我”依赖于 appService , 当这个控制器被创建之后,容器就会将它所需要的依赖传递给它也就是注入。

当然 nestjs 中还需要一个 Module 进行依赖注入,这个 Module 就可以看成是我们的容器。

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

nestjs 我还不是很熟悉,如果有错误还望指出

应用

import { Injectable } from "injector"
import { Engine } from "engine"

@Injectable()
class SDKHelper {

	constructor(private engine: Engine){ }
    
    	doSomething() {
    		// xxx
            this.engine.xxx()
    	}
}

这里我对我们要做的事情做了一个简单的打样,对我们引入的 SDK 做一个全局的实例管理,也就是我们常说的单例模式,全局维护一个实例。后续将各个组件中所需要的状态或者变量再度交给容器进行管理。组件内部只处理单一逻辑。这样也便于埋点、维护、扩展等。

结尾

首先,给大家拜个早年,祝大家新年快乐,牛年大吉!以上是我对 AOPIoC 的简单理解,如果有错误,还希望各位大神指点一下。

参考: zhuanlan.zhihu.com/p/89579703