javascript为何要学习设计模式【教程】

设计模式的价值在于识别并解决经典耦合问题,而非机械套用;Factory适用于运行时配置依赖等场景;Observer适合内部状态流,EventEmitter适合I/O事件;Singleton在前端多为反模式,应优先用模块级单例或依赖注入。

JavaScript 不需要“为了学设计模式而学设计模式”。真正值得投入时间的,是当你在维护一个多人协作、生命周期超过半年、模块间耦合开始变重的项目时,发现 if 嵌套越来越深、new 出来的对象职责不清、状态散落在十几个回调里——这时候设计模式不是银弹,但能帮你把混乱显式化。

哪些场景下 Factory 比直接 new 更可靠

当构造逻辑依赖运行时配置、需要统一拦截实例化过程、或不同环境返回不同子类实例时,硬写 new SomeClass() 会快速失控。

  • 比如前端 SDK 需要根据浏览器支持情况返回 IndexedDBStorageLocalStorageFallback,用工厂函数封装判断逻辑,调用方完全不感知底层差异
  • 测试时可轻松替换工厂返回 mock 实例,避免真实副作用
  • 注意别把工厂写成巨型 switch:一旦分支超过 4 个,考虑结合 Map 或策略模式预注册构造器

ObserverEventEmitter 的边界在哪

原生 addEventListener 已经是观察者模式实现,但它的事件名是字符串、无类型约束、无法跨 iframe 或跨模块统一管理。自建轻量 Observer 类更适合内部状态流。

  • Vue 2 的响应式系统底层就是 Observer + Dep,它让数据变化和视图更新解耦,但代价是劫持 Object.defineProperty
  • Node.js 的 EventEmitter 更适合 I/O 或生命周期事件(如 'connect''error'),它自带最大监听器数警告、异步执行保障,但不适合高频状态变更(如鼠标移动)
  • 现代项目中,优先用 Proxy + 自定义钩子替代传统 Observer,避免对数组索引赋值等边界失效问题

为什么 Singleton 在前端多数是反模式

单例强调“全局唯一实例”,但在前端,页面刷新即重置、多标签页互不通信、SSR 服务端与客户端环境隔离——所谓“唯一”根本不可靠。

  • 常见误用:用单例缓存 API 响应,结果用户在另一个 tab 登录不同账号,看到旧数据
  • 真正需要的是“当前上下文唯一”,比如某个 React 组件内部的 useRef 缓存实例,或 Zustand store 的单例导出(本质是模块级单例,非全局)
  • 如果真要跨模块共享状态,用依赖注入(如通过顶层 Provider 注入)比自己 getInstance() 更可控、更易测

设计模式的价值不在名词本身,而在你能否一眼识别出“这里正在重复解决某个经典耦合问题”。与其背口诀,不如下次遇到 props 穿透三层组件时,停下来想:是不是该把这部分逻辑抽成独立的可观察对象?