js设计原则-装饰器模式
装饰器模式-Decorator
Decorator 介绍
装饰器模式( Decorator ):在不改变原对象的结构和功能上,通过对其进行包装拓展(添加属性或者方法)使原有对象可以满足用户更复杂的需求。
Decorator 示例 & UML
⓵ 手机壳
⓶ 房子装修
Decorator 代码
class Circle {
draw() {
console.log('画一个圆形')
}
}
// 装饰器
class Decoractor {
constructor(circle) {
this.circle = circle;
}
draw() {
this.circle.draw();
this.setRedBorder(circle);
}
setRedBorder(circle) {
console.log('设置红色边框');
}
}
// 测试代码
let circle = new Circle();
circle.draw();
console.log('-----分割线-----')
let dec = new Decoractor(circle);
dec.draw();
Decorator 场景
① ES7 装饰器
② core-decorators
ES7 装饰器
-
配置环境
-
装饰类
-
装饰方法
ES7配置环境
- 安装 babel-plugin-transform-decorators-legacy
cnpm i babel-plugin-transform-decorators-legacy --save-dev
- 修改.babelrc
{
"presets": ["es2015", "latest"],
"plugins": ["babel-plugin-transform-decorators-legacy"]
}
- 测试ES7环境是否安装成功
@testDec
class Demo {
}
function testDec(target) {
target.isDec = true;
}
alert(Demo.isDec)
装饰类-Class
@testDec
class Demo {
}
function testDec(target) {
target.isDec = true;
}
alert(Demo.isDec) // true
// 装饰器的原理
@decorator
class A {}
// 等同于
class A {}
A = decorator(A) || A;
// 可以加参数
function testDec(isDec) {
return function(target) {
target.isDec = isDec;
}
}
@testDec(true)
class Demo {}
alert(Demo.isDec);
装饰方法-Method
class Person {
constructor() {
this.first = 'A';
this.last = 'B';
}
// 装饰方法
@readonly
name() {
return `${this.first} ${this.last}`
}
}
function readonly(target,name, descriptor) {
// descriptor 属性描述对象 (Object.defineProperty 中会用到),原来的值如下
// {
// value: specifiedFunction,
// enumerable: false,
// configurable: true,
// writable: true
// }
descriptor.writable = false
return descriptor;
}
var p = new Person();
console.log(p.name());
// p.name = function() {} // 这里会报错,因为name 是只读属性
// 实例2
class Math {
// 装饰方法
@log
add(a, b) {
return a + b;
}
}
function log(target, name, descriptor) {
var oldValue = descriptor.value;
descriptor.value = function() {
console.log(`Calling ${name} with`, arguments);
return oldValue.apply(this, arguments);
}
return descriptor;
}
const math = new Math();
const result = math.add(2, 4); // 执行add时会自动打印日志,因为有@log装饰器
console.log(result);
core-decorators
- 安装 core-decorators
cnpm i core-decorators --save
import { readonly } from 'core-decorators';
class Person {
constructor() {
this.first = 'A';
this.last = 'B';
}
// 装饰方法
@readonly
name() {
return `${this.first} ${this.last}`
}
}
var p = new Person();
console.log(p.name());
// p.name = function() {} // 这里会报错,因为name 是只读属性
Decorator 设计原则验证
-
将现有对象和装饰器进行分离,两者独立存在
-
符合开放封闭原则