js设计模式-装饰器模式

一.概念

装饰器模式核心价值:

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

二.使用举例

  1. 原型扩展
javascript 复制代码
<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. 工具函数扩展
javascript 复制代码
<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. 日志记录
    实现对函数调用的跟踪,不改动原函数逻辑
javascript 复制代码
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. 性能分析
    测量函数执行时间
javascript 复制代码
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.参数校验

确保函数参数符合规范

javascript 复制代码
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)中得到了广泛采用,是构建可扩展系统的核心策略

相关推荐
Mh2 分钟前
如何优雅的消除“if...else...”
前端·javascript
lapiii35837 分钟前
[前端-React] Hook
前端·javascript·react.js
小飞大王66638 分钟前
JavaScript基础知识总结(六)模块化规范
开发语言·javascript·ecmascript
一枚前端小能手1 小时前
🎬 使用 Web 动画 API - 关键帧与交互控制实战指南
前端·javascript·api
西西学代码1 小时前
Flutter---异步编程
开发语言·前端·javascript
guangzan1 小时前
常用设计模式:模板方法模式
设计模式
米欧1 小时前
取消当前正在进行的所有接口请求
前端·javascript·axios
浪里行舟1 小时前
告别“拼接”,迈入“原生”:文心5.0如何用「原生全模态」重塑AI天花板?
前端·javascript·后端
努力学前端Hang2 小时前
移动端跨平台开发深度解析:UniApp、Taro、Flutter 与 React Native 对比
前端·javascript·react native·react.js
前端九哥2 小时前
🚫循环里写return,浏览器当场沉默!
前端·javascript