美文网首页
设计模式之装饰者模式

设计模式之装饰者模式

作者: 回调的幸福时光 | 来源:发表于2019-06-17 17:52 被阅读0次

    一、基础介绍

    在不改变原对象的基础上,给对象动态增加职责(功能:属性或方法)的方式称为装饰者模式。

    装饰者模式 UML 类图

    二、装饰函数

    2.1 通过保存原引用的方式

    如果需要绑定 onload 事件,但又不确定是否别人已经绑定过,为了避免覆盖掉之前的 window.onload 函数中的行为,常见的做法是:

    var _onload = window.onload || function() {};
    
    window.onload = function() {
      _onload();
      // do otherthing
    }
    

    缺点:

    • 需要维护 _onload 这个中间变量
      如果函数的装饰链较长,或者需要装饰的函数变多,这些中间变量的数量会越来越多。
    • this 被劫持
      当调用一个全局函数时,this 是指向 window 的,但是保存的原引用所指向的函数内部可能对于 this 的指向有特定的要求。(例如:document.getElementId)
    2.2 用 AOP 装饰函数
    Function.prototype.before = function (beforefn) {
      var _self = this; // 保存原函数的引用
      return function () {
        beforefn.apply(this, arguments); // 执行新函数,且保证 this 不被劫持
        _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;
      }
    }
    

    如果不喜欢上面污染原型的方式,可采用下面的方式:

    function before(fn, beforefn) {
      return function () {
        beforefn.apply(this, arguments);
        return fn.apply(this, arguments);
      }
    }
    
    function after(fn, afterfn) {
      return function () {
        var ret = fn.apply(this, arguments);
        afterfn.apply(this, arguments);
        return ret;
      }
    }
    
    2.3 ES7 Decorator

    推荐阅读 阮一峰: 装饰器

    三、装饰者模式和代理模式的区别

    相同点:

    • 不改变原有接口
    • 这两种模式都描述了怎样为对象提供一定程度上的间接引用。

    不同点:
    代理模式的目的:当直接访问本体不方便或者不符合需要时,为本体提供一个替代者,控制对本体的访问。
    代理模式强调 Proxy 与它的实体之间的关系。
    代理模式通常只有一层代理-本体的引用。

    装饰者模式的目的:为对象动态加入行为。
    装饰者模式经常会形成一条长长的装饰链。

    装饰者模式和适配器模式的区别

    相同点: 不改变原有接口。

    适配器的目的在于解决两个接口不兼容。

    参考

    《JavaScript 设计模式与开发实践》曾探
    《JavaScript 设计模式》张容铭
    Javascript设计模式系统讲解与应用

    相关文章

      网友评论

          本文标题:设计模式之装饰者模式

          本文链接:https://www.haomeiwen.com/subject/zoaafctx.html