Skip to content
On this page

装饰器模式

介绍

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

传统 UML 类图

简化 UML 类图

javascript
class Circle {
    draw(){
        console.Log("画一个圆形")
    }
}
class Decorator {
    constructor(circle) {
        this.circle = circle
    }
    draw() {
        this.circle.draw()
        this.setRedBorder(circle)
    }
    setRedBorder(circle){
        console.log('设置红色边框')
    }
}

// 测试代码
let circle = new Circle()
circle.draw()

let dec = new Decorator(circle)
dec.draw()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

场景 - 装饰类

javascript
//一个简单的 demo
@testDec
class Demo {
    // ...
}

function testDec(target) {
    target.isDec = true;
}
alert(Demo.isDec) // true
1
2
3
4
5
6
7
8
9
10
javascript
// 装饰器的原理
@decorator
class A {}

// 等同于
cLass A {}
A = decorator(A) || A;
1
2
3
4
5
6
7

装饰器 - mixin 示例

javascript
function mixins(...list) {
  return function (target) {
    Object.assign(target.prototype, ...list)
  }
}

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

@mixins(Foo)
class MyClass {}

let obj = new MyClass();
obj.foo() // 'foo'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

场景 - 装饰方法

装饰方法一例 1

javascript
function readonly(target, name, descriptor){
  // descriptor对象原来的值如下
  // {
  //   value: specifiedFunction,
  //   enumerable: false,
  //   configurable: true,
  //   writable: true
  // };
  descriptor.writable = false;
  return descriptor;
}

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

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

var p = new Person()
console.log(p.name())
p.name = function () {} // 这里会报错,因为 name 是只读属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

装饰方法一例 2

javascript
function log(target, name, descriptor) {
  var oldValue = descriptor.value;

  descriptor.value = function() {
    console.log(`Calling ${name} with`, arguments);
    return oldValue.apply(this, arguments);
  };

  return descriptor;
}

class Math {
  @log
  add(a, b) {
    return a + b;
  }
}

const math = new Math();
const result = math.add(2, 4);
console.log('result', result); // add [Object] //result 6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

core-decorators 的使用

javascript
// import { readonly } from 'core-decorators'

// class Person {
//     @readonly
//     name() {
//         return 'zhang'
//     }
// }

// let p = new Person()
// alert(p.name())
// // p.name = function () { /*...*/ }  // 此处会报错


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();
// DEPRECATION Person#facepalm: This function will be removed in future versions.

person.facepalmHard();
// DEPRECATION Person#facepalmHard: We stopped facepalming

person.facepalmHarder();
// DEPRECATION Person#facepalmHarder: We stopped facepalming
//
//     See http://knowyourmeme.com/memes/facepalm for more details.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

设计原则验证

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