# 装饰器模式

# 介绍

  • 为对象添加新功能
  • 不改变其原有的结构和功能

# UML 类图

在这里插入图片描述

# 代码示例

class Circle {
  draw() {
    console.log('画一个圆形')
  }
}
class Decorator {
  constructor(circle) {
    this.circle = circle
  }
  draw() {
    this.circle.draw()
    this.setRedBorder(this.circle)
  }
  setRedBorder(circle) {
    console.log('设置红色边框')
  }
}
// 测试代码

let circle = new Circle()
circle.draw()
let dec = new Decorator(circle)
dec.draw()

# 场景

# ES7 装饰器

  • 配置环境

安装插件:npm install --save-dev @babel/plugin-proposal-decorators, 然后在.babelrc中进行添加插件:

{
  "presets": ["@babel/preset-env"],
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }]
  ]
}
  • 装饰类
@testDec
class Demo {

}
function testDec(target) {
  target.isDec = true
}
console.log(Demo.isDec) // true

// 装饰器的原理
@decorator
class A {}

// 等同于
class A {}
A = decorator(A) || A


// 可以带参数
function testDec(isDec) {
  return function(target) {
    console.log(target)
    target.isDec = isDec
  }
}

@testDec(false)
class Demo {

}
console.log(Demo.isDec)

// 装饰类-mixin示例
function mixins(...list) {
  return function(target) {
    Object.assign(target.prototype, ...list)
  }
}

const Foo = {
  foo() {
    console.log('foo')
  }
}
@mixins(Foo)
class MyClass {

}
let obj = new MyClass()
obj.foo()
  • 装饰方法
function readonly(target, name, descriptor) {
  descriptor.writable = false
  return descriptor
}
class Person {
  constructor() {
    this.first = 'A'
    this.last = 'B'
  }
  // 只读属性
  @readonly
  name() {
    return `${this.first} ${this.last}`
  }
}
// 测试代码
let p = new Person()
console.log(p.name())
p.name = function () {
  console.log('100')
}
console.log(p.name())

// 添加日志
function log(target, name, descriptor) {
  let oldValue = descriptor.value
  descriptor.value = function () {
    // name 就是属性名
    console.log(`calling ${name} with `, arguments)
    return oldValue.apply(this, arguments)
  }
  return descriptor
}
class Math {
  @log
  add(a, b) {
    return a + b
  }
}
// 测试代码
let math = new Math()
const result = math.add(2, 4)
console.log(result)

# core-decorators

  • 第三方开源lib
  • 提供常用的装饰器

首先进行安装npm install core-decorators --save

import { readonly } from 'core-decorators'
class Person {
  @readonly
  name() {
    return 'jiegiser'
  }
}
let p = new Person()
console.log(p.name())
p.name = function() {} // index.js:528 Uncaught TypeError: Cannot assign to read only property 'name' of object '#<Person>'

// deprecate 的使用
import { deprecate } from 'core-decorators'

class Person {
  @deprecate('即将废弃', {
    url: 'www.jiegiser.win'
  })
  name() {
    return 'jiegiser'
  }
}
let p = new Person()
console.log(p.name()) //deprecate.js:31 DEPRECATION Person#name: 即将废弃
// See www.jiegiser.win for more details.

# 设计原则验证

  • 将现有对象和装饰器进行分离,两者独立存在
  • 符合开放封闭原则

评 论:

更新: 11/21/2020, 7:00:56 PM