# 装饰器模式
# 介绍
- 为对象添加新功能
- 不改变其原有的结构和功能
# UML 类图
# 代码示例
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()
# 场景
# ES7 装饰器
- 配置环境
安装插件:npm install --save-dev @babel/plugin-proposal-decorators, 然后在.babelrc中进行添加插件:
{
"presets": ["@babel/preset-env"],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }]
]
}
- 装饰类
@testDec
class Demo {
}
function testDec(target) {
target.isDec = true
}
console.log(Demo.isDec) // true
// 装饰器的原理
@decorator
class A {}
// 等同于
class A {}
A = decorator(A) || A
// 可以带参数
function testDec(isDec) {
return function(target) {
console.log(target)
target.isDec = isDec
}
}
@testDec(false)
class Demo {
}
console.log(Demo.isDec)
// 装饰类-mixin示例
function mixins(...list) {
return function(target) {
Object.assign(target.prototype, ...list)
}
}
const Foo = {
foo() {
console.log('foo')
}
}
@mixins(Foo)
class MyClass {
}
let obj = new MyClass()
obj.foo()
- 装饰方法
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 () {
console.log('100')
}
console.log(p.name())
// 添加日志
function log(target, name, descriptor) {
let oldValue = descriptor.value
descriptor.value = function () {
// name 就是属性名
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)
# core-decorators
- 第三方开源lib
- 提供常用的装饰器
首先进行安装npm install core-decorators --save
import { readonly } from 'core-decorators'
class Person {
@readonly
name() {
return 'jiegiser'
}
}
let p = new Person()
console.log(p.name())
p.name = function() {} // index.js:528 Uncaught TypeError: Cannot assign to read only property 'name' of object '#<Person>'
// deprecate 的使用
import { deprecate } from 'core-decorators'
class Person {
@deprecate('即将废弃', {
url: 'www.jiegiser.win'
})
name() {
return 'jiegiser'
}
}
let p = new Person()
console.log(p.name()) //deprecate.js:31 DEPRECATION Person#name: 即将废弃
// See www.jiegiser.win for more details.
# 设计原则验证
- 将现有对象和装饰器进行分离,两者独立存在
- 符合开放封闭原则
阅读量: