JavaScript设计模式是解决特定问题的对象组织方式和协作关系,决定代码可维护性、可测试性与协作效率;单例确保全局唯一实例,工厂封装对象创建逻辑,观察者实现松耦合通信。

单例模式:为什么 new DatabaseConnection() 不能随便写
当你需要全局唯一资源(比如日志器、配置管理器、WebSocket 连接),每次 new 都会创建新实例,轻则浪费内存,重则导致状态错乱或连接泄漏。
- 错误做法:
const logger1 = new Logger(); const logger2 = new Logger();—— 两个独立实例,日志可能写到不同文件或丢失上下文 - 正确做法:用私有静态属性 + 构造拦截,确保
Logger.getInstance()总返回同一个对象 - 注意惰性初始化:实例只在第一次调用
getInstance()时创建,避免页面加载就占资源 - ES6 class 实现时别忘了在构造函数里检查
if (Logger.instance) return Logger.instance,否则new仍可绕过控制
工厂模式:当 if/else 创建对象开始蔓延时就得收手
你是不是写过这样的代码:if (role === 'admin') { return new AdminUser(); } else if (role === 'vip') { ... }?这种逻辑一旦散落在多个文件里,改一个角色就要全局搜、逐个修。
技术上面应用了三层结构,AJAX框架,URL重写等基础的开发。并用了动软的代码生成器及数据访问类,加进了一些自己用到的小功能,算是整理了一些自己的操作类。系统设计上面说不出用什么模式,大体设计是后台分两级分类,设置好一级之后,再设置二级并选择栏目类型,如内容,列表,上传文件,新窗口等。这样就可以生成无限多个二级分类,也就是网站栏目。对于扩展性来说,如果有新的需求可以直接加一个栏目类型并新加功能操作
- 工厂本质是把“怎么造”藏起来,暴露统一接口:
UserFactory.create('admin') - 适合场景:API 返回不同类型数据需映射为不同类;组件按权限动态加载;表单校验规则按字段类型分发
- 进阶技巧:配合
import()动态导入,让工厂只加载当前需要的模块,避免打包体积膨胀 - 别把工厂写成巨型 switch:超过 4–5 种类型时,考虑用注册表模式(
factory.register('admin', AdminUser))解耦
观察者模式:Vue 的 $emit 和 React 的自定义 Hook 背后都是它
它解决的是「谁变了,谁通知,谁响应」的问题。不是所有通信都要用 Redux;两个组件之间状态联动,观察者往往更轻、更直接。
- 核心结构只有三样:
subscribe()订阅、notify()发布、observers存回调 - 常见坑:忘记取消订阅 → 内存泄漏(尤其在组件卸载时);用箭头函数订阅导致
this指向错乱 - 真实场景:表单联动(选城市 → 刷新区域下拉)、WebSocket 心跳失败后触发重连广播、性能监控上报完成事件
- 和发布-订阅的区别不大,但工程中建议用
EventBus类封装,避免直接操作document或window自定义事件,方便单元测试










