# 设计模式:装饰器模式

# 什么是装饰器模式

它类似于高阶函数,但不同的是。装饰器不修改函数,只是在函数之前或之后修改函数的返回值而已

# 使用场景

比如鬼剑士,带上太刀就会增加很多攻速,带上巨剑就会增加很多伤害。但增加伤害和增加速度的代码并不是鬼剑士本身实现的,而是太刀和巨剑对应的代码实现的。

很多互联网产品都想要统计用户的行为,但是又不能直接的更改我们的业务逻辑代码。那么装饰器模式就是很好的实现方法。

# Coding

装饰函数

var a = function() {
  console.log(1)
}
var _a = a
a = function() {
  _a();
  console.log(2)
}

这样做的好处是,没有修改原有的函数体。但还扩展了函数的能力。缺点是要多维护一个 _a 的变量。

AOP 装饰函数

Function.prototype.before = function(beforeFn) {
  var __self = this;
  return function() {
    beforeFn.apply(this, arguments)
    return __self.apply(this, arguments)
  }
}

Function.prototype.after = function(afterFn) {
  var __self = this;
  return function() {
    var ret = __self.apply(this, arguments)
    afterFn.apply(this, arguments)
    return ret
  }
}

var a = function() {
  console.log('1')
}

a = a.after(() => {
  console.log(2)
})
a() // 1, 2

a = a.before(() => {
  console.log(0)
})
a() // 0, 1, 2

例子:用户行为统计

<html>
  <button tag="login" id="button">点击打开登录浮层</button>
  <script>
    Function.prototype.after = function( afterfn ){
      var __self = this;
      return function(){
        var ret = __self.apply( this, arguments );
        afterfn.apply( this, arguments );
        return ret;
      }
    };
    var showLogin = function(){
      console.log( '打开登录浮层' );
    }
    var log = function(){
      console.log('用户点击了登录按钮');
    }
    showLogin = showLogin.after( log ); // 打开登录浮层之后上报数据
    document.getElementById( 'button' ).onclick = showLogin;
  </script>
</html>

# 总结

出来上面提到的统计用户行为的例子以外还有很多应用场景都可以用装饰器模式。它最大的好处是可以和原有的逻辑产生隔离。但还可以轻松的实现扩展。

上次更新: 10/19/2020, 6:24:06 PM