装饰器模式
- 为对象添加新功能
- 不改变其原有的结构和功能
class Circle {
draw() {
console.log('画一个圆形')
}
}
class Decorator {
constructor(circle) {
this.circle = circle
}
draw() {
this.circle.draw()
this.setRedBord(circle)
}
setRedBord(circle) {
console.log('设置红色边框')
}
}
// 测试
let circle = new Circle()
circle.draw()
let dec = new Decorator(circle)
dec.draw()
场景
- ES7装饰器
core-decorators
ES7装饰器
装饰类
@testDec
class Demo {
// ...
}
function testDec(target) {
target.isDec = true;
}
alert(Demo.isDec) // true
参数形式:
function testDec(isDec) {
return funciton (target) {
target.isDec = isDec
}
}
@testDec(false)
class Demo {
}
alert(Demo.isDec) // false
装饰器 - mixin示例
function mixin(...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'
装饰方法
class Person {
constructor() {
this.first = 'A'
this.last = 'B'
}
// 装饰方法 只读属性
@readonly
name() {
return `${
this.first} ${
this.last}`
}
}
const p = new Person()
console.log(p.name())
p.name = function () {
} // 报错,因为name是只读属性
@readonly
的实现
function readonly(target, name, descriptor) {
// descriptor 属性描述对象, Object.defineProperty中会用到, 原来的值如下;
// {
// value: specifiedFunction,
// enumerable: false, // 可枚举
// configurable: true, // 可配置
// writable: true // 可写
// }
descriptor.writable = false // 变为不可写
return descriptor
}
装饰方法
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)
@log装饰器方法实现
function log(target, name, descriptor) {
let oldValue = descriptor.value; // zhuan shi
descriptor.value = function() {
console.log(`Calling ${
name} with`, arguments)
reutrn oldValue.apply(this, arguments)
};
return descriptor;
}
js装饰器第三方lib库
core-decorators
import {
deprecate } from 'core-decorators' // 提示废弃
设计原则验证
- 将现有对象和装饰器进行分离,两者独立存在
- 符合开放封闭原则