优化实战 第 31 期 - 高效利器之装饰器模式

2,153 阅读3分钟

在软件开发过程中,经常会有一些与功能逻辑本身无关的、重复性的代码。可以通过装饰器模式进行抽象,在需要的地方直接进行使用即可

装饰器模式

  • 模式定义

    它是一种结构型设计模式,旨在促进代码复用,在不改变现有对象的情况下,动态地给该对象及其属性添加一些额外的职责,即扩展功能

  • 模式作用

    可以对代码逻辑进行合理拆分,轻松实现代码的 重用性低耦合性;并且与继承相比更加灵活(即插即用)

  • 模式实现

    既可以使用 ECMAScript 标准语法提供的装饰器,也可以使用 TypeScript 提供的装饰器

  • 生活示例

    在生活中经常吃的煎饼,可以在其中加鸡蛋、烤肠等,使其更加美味。但不管加啥,原先的煎饼还是那个煎饼

装饰器原理

  • 无参数装饰器

    function readonly(target, name, descriptor) {
      descriptor.writable = false
      return descriptor
    }
    
  • 多参数装饰器

    function decorationFactory(params) {  // 装饰器工厂
      return function(target, name, descriptor) {  // 装饰器
        // target 当前被装饰的对象
        // name 所要装饰的属性名称
        // descriptor 属性的描述对象,对应 Object.defineProperty 方法中的 descriptor
      }
    }
    
  • 使用方式

    @ + 函数名 放在被装饰对象的前面,可以装饰 类、类的属性、类的方法、属性存取器

  • 实现原理

    装饰器本质就是编译时执行的函数

装饰器参数详解

  • 装饰器装饰类时

    只有一个 target 参数表示类本身

  • 装饰器装饰类的方法时

    target 表示类的原型对象

    name 表示所要装饰的类方法名称

    descriptor 表示类方法的描述对象,对应 Object.defineProperty 方法中的 descriptor

    descriptor.value 表示所要装饰的类方法本身

知识扩展

  • 方法作用

    Object.defineProperty() 会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象

  • 基本语法

    Object.defineProperty(obj, prop, descriptor)
    

    obj 定义属性的对象

    prop 要定义或修改的属性名称

    descriptor 被定义或修改的属性描述符

  • 对象中的属性描述符

    enumerable 定义对象的属性是否可以在 for...inObject.keys() 中被枚举,默认值为 true 可枚举的

    const enumeration = { name: 'adiu', age: 28 }
    Object.keys(enumeration)  // ['name', 'age']
    
    Object.defineProperty(enumeration, 'age', {
      enumerable: false
    })
    Object.keys(enumeration)  // ['name']
    

    valuewritable 分别定义了属性的值(数值、对象、函数等)和 是否可以对属性进行赋值更改;前者的默认值为 undefined,后者的默认值为 true 可更改

    const enumeration = { name: 'adiu', age: 28 }
    Object.defineProperty(enumeration, 'age', {
      value: 18,
      writable: false
    })
    enumeration.age  // 18
    enumeration.age = 12  // Uncaught TypeError: Cannot assign to read only property 'age' of object '#<Object>'
    

装饰器应用

装饰器语法文档

标准 ECMAScript 装饰器语法参照文档

TypeScript 装饰器语法参照文档

一起学习,加群交流看 沸点