当前位置: 首页 > news >正文

前端开发之装饰器模式

介绍

装饰器模式 是在不修改对象内部结构的情况下,动态地给对象添加功能的一种设计模式。在软件开发中,有时候我们需要为已有对象添加一些额外的行为,但不希望修改该对象的代码,装饰器模式可以很好的满足这一需求。

在TypeScript中,装饰器是一个函数,它可以用来注入或修改类、方法、属性或参数的行为。装饰器在编译阶段被执行,它会接收被装饰的目标作为参数,并且可以返回一个新的构造函数或方法。

装饰器的使用需要在 tsconfig.json 或者 tsconfig.app.json  中启用如下配置:

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

 

class Circle {draw() {console.log("画圆");}
}class Decorator {private circle: Circle;constructor(circle: Circle) {this.circle = circle;}draw() {this.circle.draw(); // 原有功能this.setBorder(); // 装饰}private setBorder() {console.log("设置边框颜色");}
}const circle = new Circle();
const  decorator = new Decorator(circle)
decorator.draw()

符合开放封闭原则:

  1. 装饰器和目标分离,解耦
  2. 装饰器可自由扩展
  3. 目标可自由扩展

场景 

(1)类装饰器

类装饰器用于装饰整个类,通常用来扩展或修改类的功能。

function LogClass(target: Function) {console.log(`Class decorated: ${target.name}`);
}@LogClass
class ExampleClass {constructor() {console.log("ExampleClass instance created");}
}const ec = new ExampleClass()
// Class decorated: ExampleClass
// ExampleClass instance created

在这个例子中,LogClass 装饰器会在 ExampleClass 类定义时打印信息。

(2)方法装饰器

方法装饰器用于装饰类中的方法,它可以对方法进行一些增强操作,例如添加日志、性能监控等。

function LogMethod(target: any, propertyName: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function (...args: any[]) {console.log(`Method ${propertyName} called with arguments: ${args}`);return originalMethod.apply(this, args);};return descriptor;
}class Calculator {@LogMethodadd(a: number, b: number): number {return a + b;}
}const calc = new Calculator();
calc.add(2, 3);  // 输出: Method add called with arguments: 2,3

在这个例子中,LogMethod 会拦截 add 方法的调用并记录传递的参数。

 (3)属性装饰器

属性装饰器用于装饰类中的属性,它可以用来改变属性的元数据或做一些额外的处理。

function Readonly(target: any, propertyName: string) {Object.defineProperty(target, propertyName, {writable: false});
}class Person {@Readonlyname: string = "John";
}const person = new Person();
person.name = "Jane";  // 这里会报错,因为 name 是只读的

在这个例子中,Readonly 装饰器将 name 属性设置为不可修改。

 (4)参数装饰器

参数装饰器用于装饰方法的参数,它通常用于对参数进行校验或元数据的处理。

function LogParameter(target: any, methodName: string, parameterIndex: number) {console.log(`Parameter in ${methodName} at index ${parameterIndex} is decorated`);
}class User {greet(@LogParameter message: string) {console.log(message);}
}const user = new User();
user.greet("Hello!");  // 输出: Parameter in greet at index 0 is decorated

在这个例子中,LogParameter 装饰器记录了 greet 方法的参数装饰情况。

AOP

面向切面编程(AOP,Aspect Oriented Program)是一种编程范式,通过将横切关注点(例如日志、事务管理等)从主要逻辑中分离出来,提高了代码的模块化和可重用性。在 TypeScript 中,AOP 可以与装饰器模式结合使用,以在代码的不同部分(方法、函数等)应用相同的横切关注点。

一个常见的 AOP 应用场景是性能监控,例如计算方法执行时间的装饰器:

function measure(target: any, key: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function(...args: any[]) {const startTime = performance.now();const result = originalMethod.apply(this, args);const endTime = performance.now();console.log(`Method ${key} took ${(endTime - startTime).toFixed(2)} ms`);return result;};return descriptor;
}class Example {@measureprocess(data: string) {// 模拟一个耗时操作let result = '';for (let i = 0; i < 1000000; i++) {result += data;}return result;}
}const example = new Example();
const result = example.process("test"); 
// 输出方法执行时间:Method process took 32.30 ms

在这个示例中,measure 装饰器被应用于 process 方法,用来测量方法执行时间并输出日志。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 关于 SQL 的 JOIN 操作
  • chsharp文件如何查找在unity中使用的 位置?
  • 算法打卡:第十一章 图论part01
  • C#的数据类型转换
  • 电商API的创新应用与高效数据采集策略实践
  • Python用TOPSIS熵权法重构粮食系统及期刊指标权重多属性决策MCDM研究|附数据代码...
  • 【代码随想录Day25】回溯算法Part04
  • vue Echart使用
  • 数据结构之——栈
  • 【LeetCode周赛】第 416 场
  • layui时间选择器选择周 日月季度年
  • java.nio.ByteBuffer的 capacity, limit, position, mark
  • 【计算机网络强化】计网强化笔记
  • 【计算机网络 - 基础问题】每日 3 题(二十二)
  • GP2D12红外距离传感器
  • Android 控件背景颜色处理
  • ERLANG 网工修炼笔记 ---- UDP
  • Git学习与使用心得(1)—— 初始化
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • React-redux的原理以及使用
  • 创建一种深思熟虑的文化
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 从零开始学习部署
  • 订阅Forge Viewer所有的事件
  • 回顾2016
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 前端_面试
  • 强力优化Rancher k8s中国区的使用体验
  • 算法系列——算法入门之递归分而治之思想的实现
  • 移动端 h5开发相关内容总结(三)
  • 阿里云移动端播放器高级功能介绍
  • 阿里云重庆大学大数据训练营落地分享
  • 整理一些计算机基础知识!
  • ## 基础知识
  • ###C语言程序设计-----C语言学习(3)#
  • #APPINVENTOR学习记录
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • (6)STL算法之转换
  • (9)目标检测_SSD的原理
  • (附源码)php新闻发布平台 毕业设计 141646
  • (过滤器)Filter和(监听器)listener
  • (十) 初识 Docker file
  • (一)springboot2.7.6集成activit5.23.0之集成引擎
  • .mysql secret在哪_MySQL如何使用索引
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .NET IoC 容器(三)Autofac
  • .net2005怎么读string形的xml,不是xml文件。
  • /boot 内存空间不够
  • /etc/X11/xorg.conf 文件被误改后进不了图形化界面
  • ?php echo $logosrc[0];?,如何在一行中显示logo和标题?
  • @ConditionalOnProperty注解使用说明
  • @JoinTable会自动删除关联表的数据
  • @PostConstruct 注解的方法用于资源的初始化
  • [asp.net core]project.json(2)