Appearance
单例模式
0、定义
TIP
1、为对象添加新功能
2、不改变起原有的结构和功能
1、设计原则验证
- 1、将现有对象和装饰器进行分离,两者独立存在
- 2、符合开放封闭原则
2、示例
示例:手机壳

3、代码
js
class Circle {
draw() {
console.log('画一个圆形')
}
}
class Decorator {
constructor() {
this.circle = new Circle()
}
draw() {
this.circle.draw()
this.setRedBorder(circle)
}
setRedBorder(circle) {
console.log('设置红色边框')
}
}
// 测试
let circle = new Circle()
circle.draw()
console.log('--------分割线---------')
let dec = new Decorator(circle)
dec.draw()4、经典场景
4.1、ES7装饰器
js
// 安装插件
npm install @babel/plugin-proposal-decorators --save-dev --registry=https://registry.npm.taobao.org
// webpack配置中加入插件
options: {
presets: ['@babel/preset-env'],
plugins: [
['@babel/plugin-proposal-decorators', {'legacy': true }]
]
}
// 环境测试代码
@testDec
class Demo {
}
function testDec(target) {
target.isDec = true
}
alert(Demo.isDec)4.2、示例1
js
function testDec(isDec) {
return function(target) {
target.isDec = isDec
}
}
@testDec(false)
class Demo {
}
alert(Demo.isDec)4.3、示例2-参数
js
function mixins(...list) {
return function(target) {
Object.assign(target.prototype, ...list)
}
}
const Foo = {
foo() {
alert('foo')
}
}
@mixins(Foo)
class MyClass {
}
let obj = new MyClass()
obj.foo()4.4、示例3-只读属性
js
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())4.5、示例4-打印log
js
function log(target, name, descriptor) {
let oldValue = descriptor.value
descriptor.value = function() {
console.log(`calling ${name} width `, 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)4.6、类库:core-decorators
js
npm i core-decorators --save --registry=https://registry.npm.taobao.orgjs
// 案例1
import { readonly } from 'core-decorators'
class Person {
@readonly
name() {
return 'zhang san'
}
}
let p = new Person()
alert(p.name())
// 修改报错: Cannot assign to read only property 'name' of object '#<Person>'
p.name = function () {
}js
// 案例2
import { deprecate } from 'core-decorators'
class Person {
@deprecate('即将废用', {url: 'www.baidu.com'})
name() {
return 'zhang san'
}
}
let p = new Person()
alert(p.name())