对于装饰器模式的理解,可以举例。在手机上可以套上一个手机壳,不会影响手机的正常使用功能,可以给手机起到装饰的作用,并且保护手机不受到伤害。
对于装饰器模式的应用场景,比如 ES7 装饰器,core-decorators 等等。
装饰器模式的设计原则验证,将现有对象和装饰器进行分离,两者独立存在,符合开放封闭原则。
介绍
// 等同于 class Demo {} Demo = decorator(Demo) || Demo;
<a name="4LfMV"></a>
# 常见使用场景
- 装饰类
```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();
<a name="i9iMF"></a>
# 装饰器模式代码示例
```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();
设计原理验证
- 将旧接口和使用者进行分离
- 符合开放封闭原则