介绍
- 为对象添加新功能
- 不改变其原有的结构和功能
UML类图
代码演示
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 decorator = new Decorator(circle);
decorator.draw();
场景
ES7装饰器
- 装饰类
简单demo:
// 简单demo
@testDec
class Demo {
}
function testDec(target) {
target.isDec = true
}
alert(Demo.isDec)
可以传参数:
// 可以加参数
function testDec(isDec) {
return function(target) {
target.isDec = isDec;
}
}
@testDec(true)
class Demo {
// ...
}
alert(Demo.isDec) // true
mixin示例:
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:
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是只读属性
function readonly(target, name, descriptor) {
// descriptor属性描述对象(Object.defineProperty中会用到),原来的值如下
//{
// value: specifiedFunction,
// enumerable: false,
// configurable: true,
// writable: true
//};
descriptor.writable = false;
return descriptor;
}
例2:
class Math {
// 装饰方法
@log
add(a, b) {
return a + b;
}
}
const math = new Math();
const result = math.add(2, 4); // 执行add时,会自动打印日志,因为有@log装饰器
console.log('result', result);
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;
}
core-decorators
// 首先安装 npm i core-decotators --save
// 开始编码:
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() {}
}
设计原则验证
- 将现有对象和装饰器进行分离,两者独立存在
- 符合开放封闭原则