背景

Nest是围绕一种称为装饰器的语言特性构建的。

装饰器风格的实现

Nest在面向对象设计中用到了装饰器模式去组织代码。

装饰器模式是一种动态地往一个类别中添加新的行为的设计模式

在写项目的时候,可以说处处都是围绕着装饰器模式去进行定义的。

例如将一个类定义为一个controller,并将方法暴露为Get请求的方法是像下面这样处理:

import { Controller, Get } from '@nestjs/common';@Controller('cats')
export class CatsController {@Get()findAll(): string {return 'This action returns all cats';}
}

而能使用装饰器,其实还是因为js提供了支持。具体细节可以看看Typescript的装饰器文档。

装饰器是JavaScript 的第 2 阶段提案,可作为 TypeScript 的实验性功能使用

装饰器提供了一种为类声明和成员添加注释和元编程语法的方法。因此,很多装饰器,其实就是应用reflect-metadata包,去定义各种元数据。

Reflect Metadata 是 ES7 的一个提案,它主要用来在声明的时候添加和读取元数据。

因为这些js提供的语言特性,我们在使用时,就需要在tsconfig.json中配置compileOptions的参数:

{"compilerOptions": {"target": "ES5","experimentalDecorators": true,"emitDecoratorMetadata": true}
}

大多数场景下,装饰器其实都是在对元数据进行定义或者操作。例如,下面是Nest中对Http请示装饰器的逻辑代码:

const defaultMetadata = {[PATH_METADATA]: '/',[METHOD_METADATA]: RequestMethod.GET,
};export const RequestMapping = (metadata: RequestMappingMetadata = defaultMetadata,
): MethodDecorator => {const pathMetadata = metadata[PATH_METADATA];const path = pathMetadata && pathMetadata.length ? pathMetadata : '/';const requestMethod = metadata[METHOD_METADATA] || RequestMethod.GET;return (target: object,key: string | symbol,descriptor: TypedPropertyDescriptor<any>,) => {Reflect.defineMetadata(PATH_METADATA, path, descriptor.value);  // 注意这里! 元数据定义Reflect.defineMetadata(METHOD_METADATA, requestMethod, descriptor.value); // 注意这里! 元数据定义return descriptor;};
};

之前刚了解js中使用装饰器风格的时候,自己也写过一个简答的用装饰器风格封装koa的项目:deco-brick,可以结合代码理解下这里所说的。

Typescript中的decorator

Typescript提供了五种decorator:

  • Class Decorators(类装饰器)
  • Method Decorators(类方法装饰器)
  • Parameter Decorators(参数装饰器)
  • Accessor Decorators(访问器装饰器)
  • Property Decorators(类属性装饰器)

具体还是参考Typescript Decorator文档会讲得比较清楚

但是在Nest中,只用到Class Decorators(类装饰器)、Method Decorators(类方法装饰器)、Parameter Decorators(参数装饰器)三种

export declare function applyDecorators(...decorators: Array<ClassDecorator | MethodDecorator | PropertyDecorator>): <TFunction extends Function, Y>(target: object | TFunction, propertyKey?: string | symbol, descriptor?: TypedPropertyDescriptor<Y>) => void;

使用Nest提供的关于decorator的方法

创建参数装饰器——createParamDecorator

createParamDecorator是创建一个参数装饰器,提供这个方法主要的原因是我们在开发过程中,需要针对执行上下文去做一下操作,这个方法会将执行上下文传递到装饰器中。

如下:

import { createParamDecorator, ExecutionContext } from '@nestjs/common';export const User = createParamDecorator((data: unknown, ctx: ExecutionContext) => {const request = ctx.switchToHttp().getRequest(); // 将执行上下文转换成express的requestreturn request.user;},
);

组合装饰器——applyDecorators

为了逻辑代码的切分和管理,会在开发中写了多个装饰器,Nest则提供了方法去组合多个装饰器,以达到重新排练组合去复用装饰器。

import { applyDecorators } from '@nestjs/common';export function Auth(...roles: Role[]) {return applyDecorators(SetMetadata('roles', roles),UseGuards(AuthGuard, RolesGuard),ApiBearerAuth(),ApiUnauthorizedResponse({ description: 'Unauthorized' }),);
}

自定义MetaData——SetMetadata和Reflector

Nest也提供了自己去设置和获取MetaData的方法暴露出来,个人用得比较多的就是在自己编写模块的使用会用到。

下面代码是一个方法装饰器的例子

import { SetMetadata } from '@nestjs/common';// 为一个方法设置一个监听事件名
export const OnProcessEvent = (eventName: string,eventStatus: ProcessEvent,
): MethodDecorator => SetMetadata(MY_PROCESS_EVENT, { eventName, eventStatus });

而获取设置得MetaData,怎是使用@nestjs/core中的Reflector

import { Reflector } from '@nestjs/core';// 根据对象的方法获取配置的监听事件名
getEventMetadata(target: Type<any> | Function): {eventName: string;eventStatus: ProcessEvent;
} {return this.reflector.get(MY_PROCESS_EVENT, target);
}

这里的例子可以参考我的示例代码

Nest.js中的设计模式——装饰器相关推荐

  1. Python设计模式-装饰器模式

    Python设计模式-装饰器模式 代码基于3.5.2,代码如下; #coding:utf-8 #装饰器模式class Beverage():name = ""price = 0.0 ...

  2. 结构设计模式 - 装饰器设计模式

    结构设计模式 - 装饰设计模式 装饰器设计模式用于在运行时修改对象的功能.同时,同一类的其他实例不会受此影响,因此单个对象将获得已修改的行为.装饰器设计模式是结构设计模式之一(如Adapter Pat ...

  3. Angular 个人深究(一)【Angular中的Typescript 装饰器】

    Angular 个人深究[Angular中的Typescript 装饰器] 最近进入一个新的前端项目,为了能够更好地了解Angular框架,想到要研究底层代码. 注:本人前端小白一枚,文章旨在记录自己 ...

  4. Go 设计模式 - 装饰器模式

    装饰模式使用对象组合的方式动态改变或增加对象行为.Go语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式.使用匿名组合,在装饰器中不必显式定义转调原对象方法. 设计模式 装饰器模式 装饰器模式主要 ...

  5. Spring设计模式(装饰器模式)

    Spring设计模式(装饰器模式) 模式的定义: 装饰者模式定义: ​ 动态地为一个对象添加一些额外的职责,若要扩展一个对象的功能,装饰者提供了比继承更有弹性的替代方案. 模式的结构图 : 模式包含角 ...

  6. [Head First设计模式]山西面馆中的设计模式——装饰者模式

    原文:[Head First设计模式]山西面馆中的设计模式--装饰者模式 引言 在山西面馆吃鸡蛋面的时候突然想起装饰者这个模式,觉得面馆这个场景跟书中的星巴兹咖啡的场景很像,边吃边思考装饰者模式.这里 ...

  7. 第7.26节 Python中的@property装饰器定义属性访问方法getter、setter、deleter 详解

    第7.26节 Python中的@property装饰器定义属性访问方法getter.setter.deleter 详解 一.    引言 Python中的装饰器在前面接触过,老猿还没有深入展开介绍装饰 ...

  8. Python中的decorator装饰器使用方法

    装饰器的运用是Python编程中的一项高级技巧,这里由浅入深,整理了12步入门Python中的decorator装饰器使用方法,需要的朋友可以参考下 装饰器(decorator)是一种高级Python ...

  9. JS设计模式——装饰器模式

    什么是装饰器模式? 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 实例 拿最近比 ...

最新文章

  1. 为放大器模拟输入模块提供可靠的输入过电压保护
  2. 特斯拉全新自动驾驶芯片最强?英伟达回怼,投资者用脚投票
  3. ffmpeg text relocations
  4. JavaScript实现计算需要更改的位数,以便将 numberA转换为 numberB(bitsDiff)算法(附完整源码)
  5. 《软件测试方法和技术》 读书笔记
  6. Tournament CodeForces - 27B(dfs)
  7. Teradata Expression 12 在Windows 2003上Connection Reset 问题的解决方法
  8. C语言学习:%d、2d、02d、.2d的区别
  9. MySQL----商品表及商品分类表例子
  10. 开源商业化未来究竟如何?国际开源圈网红这样说
  11. OpenCV-Python图像处理教程(源码及素材)
  12. Python环境下如何安装爬虫需求的一些库
  13. 网页编码_Python获取网页编码(apparent_encoding)
  14. IIS添加对ashx文件的支持
  15. 基于RSA解题时yafu的使用
  16. 计算机画图卡通,windows画图工具怎么画卡通头像?
  17. AutoCAD_FILEDIA
  18. 图的邻接(链)表表示法 Graph adjacency list representation
  19. 随机生成10位数QQ号.c
  20. 想出名 你就这样炒作自己

热门文章

  1. 2019华为销售精英挑战赛线下海选经验--粤港澳赛区
  2. 利用spring-cloud-gateway怎么实现一个动态路由功能
  3. linux下打开iso文件怎么打开方式,Linux中打开ISO文件方法
  4. 腾讯云分布式高可靠消息队列CMQ架构
  5. 是对新生活的期待与向往
  6. 【行研报告】旅游.旅行-专题资料
  7. 更改mysql端口(全程细致)
  8. echarts隐藏掉一条曲线,并且tooltip提示框中不显示
  9. 商城quot;抢茅台quot;脚本曝光,开源可用!
  10. Python Exceptions 异常处理全过程以及异常模块详细解析