js设计模式-装饰器模式

发布于:2025-09-04 ⋅ 阅读:(13) ⋅ 点赞:(0)

一.概念

装饰器模式核心价值:

  1. 非侵入式扩展:无需修改核心功能源代码
  2. 责任链模式:通过装饰器链组合复杂逻辑
  3. 避免条件判断:消除冗余的if (featureX)代码膨胀

二.使用举例

  1. 原型扩展
<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('上报标签为: ' + this.getAttribute('tag'));
  }
  showLogin = showLogin.after(log); // 打开登录浮层之后上报数据
  document.getElementById('button').onclick = showLogin; 
</script>

</html>
  1. 工具函数扩展
<html>
  <button tag="login" id="button">点击打开登录浮层</button>

  <script>
    document.addEventListener('DOMContentLoaded', function() {
      // 工具函数:创建函数执行后的增强函数
      function composeAfter(original, afterFn) {
        return function(...args) {
          const result = original.apply(this, args);
          afterFn.apply(this, args);
          return result
        };
      }

      // 原始函数:不包含副作用
      const showLogin = () => {
        console.log('打开登录浮层');
      };

       // 副作用函数:需要访问触发元素属性
      const trackEvent = function() {
        console.log('上报标签为: ' + this.getAttribute('tag'));
      };

      // 函数组合:合并核心逻辑与监视记录
      const combinedFunction = composeAfter(showLogin, trackEvent);

      // DOM 交互封装在闭包内
      const button = document.getElementById('button');
      button.addEventListener('click', combinedFunction);
    });
  </script>
</html>

三. 应用场景

  1. 日志记录
    实现对函数调用的跟踪,不改动原函数逻辑
function logDecorator(func) {
  return function (...args) {
    console.log(`Calling ${func.name} with ${args}`);
    const result = func.apply(this, args);
    console.log(`Result: ${result}`);
    return result;
  };
}

// 使用装饰器
const add = logDecorator(function(a, b) {
  return a + b;
});

add(2, 3); // 输出调用日志
  1. 性能分析
    测量函数执行时间
function timerDecorator(func) {
  return function (...args) {
    const start = performance.now();
    const result = func.apply(this, args);
    console.log(`Time taken: ${performance.now() - start}ms`);
    return result;
  };
}

// 装饰计算密集型函数
const fibonacci = timerDecorator(function(n) {
  return n <= 1 ? n : fibonacci(n-1) + fibonacci(n-2);
});

fibonacci(30); // 输出耗时

3.参数校验
确保函数参数符合规范

function validateParams(func) {
  return function (...args) {
    args.forEach(arg => {
      if (typeof arg !== 'number') throw new Error('Invalid parameter type');
    });
    return func.apply(this, args);
  };
}

const multiply = validateParams(function(a, b) {
  return a * b;
});

multiply(2, 'three'); // 抛出参数类型错误

关键优势总结:

  1. 代码复用:将常用功能封装为装饰器库
  2. 高内聚性:避免将横切逻辑嵌入核心业务代码
  3. 可插拔性:通过装饰器叠加或替换灵活控制功能组合
  4. DRY原则:如权限验证逻辑只需维护一处

通过装饰器模式,开发者能更自然地实现"开闭原则":对扩展开放,对修改关闭。

四. 总结

通过装饰器模式,框架开发者能够:

  1. 保持核心功能的最小稳定
  2. 提供无限扩展可能性
  3. 减少因功能增加导致的维护成本指数级增长

这种将「必须功能」与「期望功能」分离的设计,在现代前端框架(如React Hooks)、中间件(如Koa)中得到了广泛采用,是构建可扩展系统的核心策略


网站公告

今日签到

点亮在社区的每一天
去签到