对于装饰器模式的理解,可以举例。在手机上可以套上一个手机壳,不会影响手机的正常使用功能,可以给手机起到装饰的作用,并且保护手机不受到伤害。 对于装饰器模式的应用场景,比如 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()
设计原理验证
- 将旧接口和使用者进行分离
- 符合开放封闭原则