Skip to content

对于装饰器模式的理解,可以举例。在手机上可以套上一个手机壳,不会影响手机的正常使用功能,可以给手机起到装饰的作用,并且保护手机不受到伤害。 对于装饰器模式的应用场景,比如 ES7 装饰器,core-decorators 等等。 装饰器模式的设计原则验证,将现有对象和装饰器进行分离,两者独立存在,符合开放封闭原则。

介绍

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

装饰器原理

javascript
@decorator
class Demo {
  // ...
}

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

常见使用场景

  • 装饰类
javascript
@testDec
class Demo {
  // ...
}

function testDec(target) {
  target.isDec = true
}

alert(Demo.isDec)
  • 装饰类-参数
javascript
@testDec(true)
class Demo {
  // ...
}

function testDec(isDec) {
  return (target) => {
    target.isDec = isDec
  }
}

alert(Demo.isDec)
  • 装饰类-mixin
javascript
function mixins(...list) {
  return (target) => {
    Object.assign(target.prototype, ...list)
  }
}

const Foo = {
  foo() {
    alert('foo')
  },
}

@mixins(Foo)
class MyClass {}

let obj = new MyClass()
obj.foo()
  • 装饰方法-1
javascript
/**
 *
 * @param {*} target
 * @param {*} name
 * @param {*} desciptor 属性描述对象,Object.defineProperty 用到,原来值(value: specifiedFunction, enumerable: false, configurable: true, writable: true)
 * @returns
 */
function readonly(target, name, desciptor) {
  desciptor.writable = false
  return desciptor
}

class Person {
  constructor() {
    this.first = 'A'
    this.last = 'B'
  }

  @readonly
  name() {
    return `${this.first}-${this.last}`
  }
}

let p = new Person()
console.log(p.name())

// 这里会报错,因为 name 是只读属性
// p.name = () => {
// 	alert("dd");
// };
  • 装饰方法-2
javascript
/**
 *
 * @param {*} target
 * @param {*} name
 * @param {*} desciptor 属性描述对象,Object.defineProperty 用到,原来值(value: specifiedFunction, enumerable: false, configurable: true, writable: true)
 * @returns
 */
function log(target, name, desciptor) {
  let oldValue = desciptor.value
  desciptor.value = () => {
    console.log(`calling ${name} width`, arguments)
    return oldValue.apply(this, arguments)
  }
  return desciptor
}

class Math {
  @log
  add(a, b) {
    return a + b
  }
}
let math = new Math()
const result = math.add(2, 4)
console.log('result', result)
  • core-decorators
javascript
import { deprecate } from 'core-decorators'

class Person {
  @deprecate
  facepalm() {}

  @deprecate('We stopped facepalming')
  facepalmHard() {}

  @deprecate('We stopped facepalming', {
    url: 'http://knowyourmeme.com/memes/facepalm',
  })
  facepalmHarder() {}
}

let person = new Person()
person.facepalm()
person.facepalmHard()
person.facepalmHarder()

装饰器模式代码示例

javascript
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()

设计原理验证

  • 将旧接口和使用者进行分离
  • 符合开放封闭原则