装饰器模式

装饰器模式,又名装饰者模式。它的定义是“在不改变原对象的基础上,通过对其进行包装扩展,使原有对象可以满足用户的更复杂需求”

介绍

为对象添加新功能

不改变七原有的结构和功能

示例

装饰器示例

代码演示

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

场景

ES7 装饰器

core-decorators

ES7 装饰器

配置环境

下载插件

babel-plugin-transform-decorators-legacy

@testDec
class Demo {}

function testDec(target) {
    target.isDec = true;
}
alert(Demo.isDec); // true

装饰器语法

class Cat {
    say() {
        console.log('meow ~');
    }
}

上面这段代码是 ES6 中定义一个类的写法,其实只是一个语法糖,而实际上当我们给一个类添加一个属性的时候,会调用到 Object.defineProperty 这个方法,它会接受三个参数:targetnamedescriptor ,所以上面的代码实际上在执行时是这样的:

function Cat() {}
Object.defineProperty(Cat.prototype, 'say', {
    value: function () {
        console.log('meow ~');
    },
    enumerable: false,
    configurable: true,
    writable: true,
});

装饰方法

例子 1

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 () {
    alert(100); // 不能写
};

例子 2

function log(target, name, descriptor) {
    let 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;
    }
}

let math = new Math();
const result = math.add(2, 4);
console.log('result', result);

core-decorators

第三方库

好用

设计原则

将现有对象和装饰器进行分离,两者独立存在

符合开发封闭原则

参考资料

Last Updated:
Contributors: johan