手撕前端七大设计模式:从理论到实战的全链路解析

一、工厂模式:批量生产对象的标准化流程

核心原理

工厂模式通过封装对象创建逻辑,将具体实现细节与使用方解耦。开发者只需调用统一的工厂接口,即可获取符合预期的实例对象,如同汽车制造厂通过流水线生产不同型号的车辆,消费者无需了解发动机装配细节。

前端典型应用

  1. Vue3实例工厂
    Vue3的createApp()方法封装了实例初始化、依赖注入等复杂逻辑,开发者通过createApp(App).mount('#app')即可完成应用启动,避免了直接操作Vue构造函数带来的风险。

  2. HTTP客户端定制
    主流HTTP库提供的工厂方法(如axios.create())允许基于默认配置创建独立实例,有效隔离不同业务模块的请求配置,防止全局配置污染导致的意外行为。

  3. 动态组件系统
    在复杂中后台系统中,可通过工厂模式实现弹窗组件的动态生成。例如根据配置对象自动创建包含表单验证、异步提交等功能的对话框实例,统一管理生命周期和样式规范。

代码实现:可扩展的请求工厂

  1. class HttpFactory {
  2. static create(config = {}) {
  3. const defaultConfig = {
  4. baseURL: '',
  5. timeout: 5000,
  6. headers: { 'X-Requested-With': 'XMLHttpRequest' }
  7. };
  8. const mergedConfig = { ...defaultConfig, ...config };
  9. const request = async (options) => {
  10. const { url, method = 'GET', data } = options;
  11. try {
  12. const response = await fetch(`${mergedConfig.baseURL}${url}`, {
  13. method,
  14. headers: mergedConfig.headers,
  15. body: method !== 'GET' ? JSON.stringify(data) : null
  16. });
  17. return await response.json();
  18. } catch (error) {
  19. console.error('Request Error:', error);
  20. throw error;
  21. }
  22. };
  23. return {
  24. get: (url, params) => request({ url, params }),
  25. post: (url, data) => request({ url, method: 'POST', data }),
  26. // 可扩展其他HTTP方法
  27. put: (url, data) => request({ url, method: 'PUT', data })
  28. };
  29. }
  30. }
  31. // 使用示例
  32. const userService = HttpFactory.create({ baseURL: '/api/users' });
  33. const orderService = HttpFactory.create({
  34. baseURL: '/api/orders',
  35. timeout: 10000
  36. });

二、单例模式:全局唯一状态管理

设计本质

确保某个类只有一个实例,并提供全局访问点。典型应用场景包括全局配置管理、日志记录器、数据库连接池等需要严格控制资源数量的场景。

前端实践案例

  1. 全局状态管理
    在小型应用中,可通过单例模式实现简单的状态管理,避免多个Store实例导致的数据不同步问题。

  2. 浏览器API封装
    localStorageIntersectionObserver等浏览器API进行单例封装,统一处理兼容性问题和错误边界。

  3. 弹窗管理器
    实现全局唯一的弹窗控制器,防止重复创建相同类型的对话框,同时管理弹窗的堆叠顺序和遮罩层。

代码实现:带缓存的API请求单例

  1. class ApiClient {
  2. static #instance = null;
  3. #cache = new Map();
  4. static getInstance() {
  5. if (!this.#instance) {
  6. this.#instance = new ApiClient();
  7. }
  8. return this.#instance;
  9. }
  10. async fetchWithCache(url) {
  11. if (this.#cache.has(url)) {
  12. return this.#cache.get(url);
  13. }
  14. try {
  15. const response = await fetch(url);
  16. const data = await response.json();
  17. this.#cache.set(url, data);
  18. return data;
  19. } catch (error) {
  20. console.error('Fetch error:', error);
  21. throw error;
  22. }
  23. }
  24. }
  25. // 使用示例
  26. const api = ApiClient.getInstance();
  27. api.fetchWithCache('/api/data').then(console.log);

三、观察者模式:解耦事件通信

模式解析

定义对象间的一对多依赖关系,当目标对象状态改变时,所有依赖它的对象都会自动收到通知。前端开发中广泛应用于事件处理、状态同步等场景。

典型应用场景

  1. DOM事件系统
    浏览器原生事件机制本质就是观察者模式的实现,通过addEventListener注册监听器,事件触发时自动通知所有订阅者。

  2. Vue响应式系统
    Vue2的Object.defineProperty和Vue3的Proxy实现,本质上都是观察者模式的变体,通过依赖收集和派发更新实现数据变化时的视图自动更新。

  3. 自定义事件总线
    在复杂组件通信场景中,可通过事件总线实现跨层级组件通信,避免props层层传递或ref直接调用的强耦合问题。

代码实现:可扩展的事件总线

  1. class EventBus {
  2. #events = new Map();
  3. on(event, callback) {
  4. if (!this.#events.has(event)) {
  5. this.#events.set(event, new Set());
  6. }
  7. this.#events.get(event).add(callback);
  8. }
  9. emit(event, ...args) {
  10. const callbacks = this.#events.get(event) || new Set();
  11. callbacks.forEach(callback => callback(...args));
  12. }
  13. off(event, callback) {
  14. const callbacks = this.#events.get(event);
  15. if (callbacks) {
  16. callbacks.delete(callback);
  17. }
  18. }
  19. }
  20. // 使用示例
  21. const bus = new EventBus();
  22. const handler = (data) => console.log('Received:', data);
  23. bus.on('message', handler);
  24. bus.emit('message', { text: 'Hello' }); // 输出: Received: { text: 'Hello' }
  25. bus.off('message', handler);

四、策略模式:动态行为封装

核心价值

将算法封装成独立对象,使它们可以相互替换。策略模式使算法的变化独立于使用算法的客户端,特别适用于需要动态切换业务逻辑的场景。

前端应用实践

  1. 表单验证规则
    为不同表单字段定义验证策略(如邮箱格式、密码强度、必填项等),运行时根据字段类型动态选择验证逻辑。

  2. 支付方式选择
    在电商系统中,将不同支付渠道(支付宝、微信、银行卡)的支付流程封装为策略对象,通过统一接口调用具体支付逻辑。

  3. 数据可视化渲染
    根据用户选择的图表类型(折线图、柱状图、饼图),动态加载对应的渲染策略,实现统一的图表容器与多样化的展示方式。

代码实现:灵活的表单验证系统

  1. const validationStrategies = {
  2. required: (value) => !!value || '此项为必填项',
  3. email: (value) => /^\S+@\S+\.\S+$/.test(value) || '请输入有效邮箱',
  4. minLength: (min) => (value) =>
  5. value.length >= min || `长度不能小于${min}位`
  6. };
  7. class Validator {
  8. constructor() {
  9. this.strategies = new Set();
  10. }
  11. addStrategy(strategy, ...args) {
  12. if (typeof strategy === 'string') {
  13. const strategyFn = validationStrategies[strategy];
  14. if (strategyFn) {
  15. this.strategies.add(strategyFn(...args));
  16. }
  17. } else {
  18. this.strategies.add(strategy);
  19. }
  20. return this;
  21. }
  22. validate(value) {
  23. for (const strategy of this.strategies) {
  24. const error = strategy(value);
  25. if (error !== true) return error;
  26. }
  27. return true;
  28. }
  29. }
  30. // 使用示例
  31. const validator = new Validator()
  32. .addStrategy('required')
  33. .addStrategy('email')
  34. .addStrategy('minLength', 6);
  35. console.log(validator.validate('test@')); // 输出: 请输入有效邮箱

(后续模式解析建议继续扩展:装饰器模式实现AOP编程、适配器模式解决接口兼容、状态模式管理复杂状态机等,每个模式保持上述结构:原理说明→应用场景→代码实现→最佳实践建议。由于篇幅限制,此处展示核心框架,完整实现可参考设计模式经典著作结合前端工程实践进行深化。)