Nest.js中的设计模式——装饰器
背景
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中的设计模式——装饰器相关推荐
- Python设计模式-装饰器模式
Python设计模式-装饰器模式 代码基于3.5.2,代码如下; #coding:utf-8 #装饰器模式class Beverage():name = ""price = 0.0 ...
- 结构设计模式 - 装饰器设计模式
结构设计模式 - 装饰设计模式 装饰器设计模式用于在运行时修改对象的功能.同时,同一类的其他实例不会受此影响,因此单个对象将获得已修改的行为.装饰器设计模式是结构设计模式之一(如Adapter Pat ...
- Angular 个人深究(一)【Angular中的Typescript 装饰器】
Angular 个人深究[Angular中的Typescript 装饰器] 最近进入一个新的前端项目,为了能够更好地了解Angular框架,想到要研究底层代码. 注:本人前端小白一枚,文章旨在记录自己 ...
- Go 设计模式 - 装饰器模式
装饰模式使用对象组合的方式动态改变或增加对象行为.Go语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式.使用匿名组合,在装饰器中不必显式定义转调原对象方法. 设计模式 装饰器模式 装饰器模式主要 ...
- Spring设计模式(装饰器模式)
Spring设计模式(装饰器模式) 模式的定义: 装饰者模式定义: 动态地为一个对象添加一些额外的职责,若要扩展一个对象的功能,装饰者提供了比继承更有弹性的替代方案. 模式的结构图 : 模式包含角 ...
- [Head First设计模式]山西面馆中的设计模式——装饰者模式
原文:[Head First设计模式]山西面馆中的设计模式--装饰者模式 引言 在山西面馆吃鸡蛋面的时候突然想起装饰者这个模式,觉得面馆这个场景跟书中的星巴兹咖啡的场景很像,边吃边思考装饰者模式.这里 ...
- 第7.26节 Python中的@property装饰器定义属性访问方法getter、setter、deleter 详解
第7.26节 Python中的@property装饰器定义属性访问方法getter.setter.deleter 详解 一. 引言 Python中的装饰器在前面接触过,老猿还没有深入展开介绍装饰 ...
- Python中的decorator装饰器使用方法
装饰器的运用是Python编程中的一项高级技巧,这里由浅入深,整理了12步入门Python中的decorator装饰器使用方法,需要的朋友可以参考下 装饰器(decorator)是一种高级Python ...
- JS设计模式——装饰器模式
什么是装饰器模式? 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 实例 拿最近比 ...
最新文章
- 为放大器模拟输入模块提供可靠的输入过电压保护
- 特斯拉全新自动驾驶芯片最强?英伟达回怼,投资者用脚投票
- ffmpeg text relocations
- JavaScript实现计算需要更改的位数,以便将 numberA转换为 numberB(bitsDiff)算法(附完整源码)
- 《软件测试方法和技术》 读书笔记
- Tournament CodeForces - 27B(dfs)
- Teradata Expression 12 在Windows 2003上Connection Reset 问题的解决方法
- C语言学习:%d、2d、02d、.2d的区别
- MySQL----商品表及商品分类表例子
- 开源商业化未来究竟如何?国际开源圈网红这样说
- OpenCV-Python图像处理教程(源码及素材)
- Python环境下如何安装爬虫需求的一些库
- 网页编码_Python获取网页编码(apparent_encoding)
- IIS添加对ashx文件的支持
- 基于RSA解题时yafu的使用
- 计算机画图卡通,windows画图工具怎么画卡通头像?
- AutoCAD_FILEDIA
- 图的邻接(链)表表示法 Graph adjacency list representation
- 随机生成10位数QQ号.c
- 想出名 你就这样炒作自己