装饰器模式

◆ 为对象添加新功能
◆ 不改变其原有的结构和功能

应用场景:
◆ ES7装饰器
◆ core-decorators


image.png

装饰器模式符合的设计原则:
◆ 将现有对象和装饰器进行分离,两者独立存在
◆ 符合开放封闭原则

1. 装饰器模式demo

class Circle {
  draw() {
    console. Log( '画一个圆形' )
  }
}
class Decorator {
  constructor(circle) {
    this.circle = circle
  }
  draw() {
    this.circle.draw()
    this.setRedBorder(circle)
  }
  setRedBorder(circle) {
    console.log( '设置红色边框')
  }
}

let circle = new Circle()
circle.draw()
let dec = new Decorator(circle)
dec.draw()

使用es7修饰符,首先我们需要安装@babel/plugin-proposal-decorators来编译es7

@testable
class MyTestableClass {
  // ...
}

function testable(target) {
  target.isTestable = true;
}

alert(MyTestableClass.isTestable) // true

// 加参数
function testDec(isDec) {
  return function(target) {
    target.isDec = isDec ;
  }
}

@testDec(true)
class Demo {
  // ...
}
alert(Demo.isDec) // true

2. 装饰器原理

// 装饰器的原理
adecorator
class A {}

//等同于
class A {}
A = decorator(A) || A;

个人感觉可参考面向切面编程,参考文章:面向切面AOP

3. mixin

将Foo合并到MyClass原型链上

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() // 'foo'

4. 装饰方法

4.1 将name方法改为只读属性

function readonly(target, name, descriptor){
  // descriptor对象原来的值如下
  // {
  //   value: specifiedFunction,
  //   enumerable: false,
  //   configurable: true,
  //   writable: true
  // };
  descriptor.writable = false;
  return descriptor;
}

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 是只读属性

4.2 打印日志

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;
}

class Math {
  @log
  add(a, b) {
    return a + b;
  }
}

const math = new Math();
const result = math.add(2, 4); Calling add with Arguments(2) [2, 4, callee: ƒ, Symbol(Symbol.iterator): ƒ]
console.log('result', result); // result 6

5. 第三方装饰器库core-decorators

github地址:https://github.com/jayphelps/core-decorators

使用方法:

  1. 只读修饰器
import { readonly } from 'core-decorators'

class Person {
    @readonly
    name() {
        return 'zhang'
    }
}

let p = new Person()
alert(p.name())
// p.name = function () { /*...*/ }  // 此处会报错
  1. 提示弃用方法
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();
// DEPRECATION Person#facepalm: This function will be removed in future versions.

person.facepalmHard();
// DEPRECATION Person#facepalmHard: We stopped facepalming

person.facepalmHarder();
// DEPRECATION Person#facepalmHarder: We stopped facepalming
// See http://knowyourmeme.com/memes/facepalm for more details.

你可能感兴趣的:(装饰器模式)