Files
test-repo/docs/zh-cn/appendix/9-engineering-excellence/design-patterns.md
T
sanbuphy f35cddeb8b feat(appendix): 重构工程实践章节,添加交互式演示组件
## 新增组件 (14个)
- CodeSmellDemo.vue: 代码异味识别演示
- DecisionMatrixDemo.vue: 决策矩阵工具
- DesignPatternCatalogDemo.vue: 设计模式目录
- DocStructureDemo.vue: 文档结构示例
- LicenseComparisonDemo.vue: 开源许可证对比
- OpenSourceWorkflowDemo.vue: 开源协作流程
- PatternPlaygroundDemo.vue: 设计模式演练场
- RefactoringDemo.vue: 重构实战演示
- SecurityChecklistDemo.vue: 安全检查清单
- TDDCycleDemo.vue: TDD 循环演示
- TechRadarDemo.vue: 技术雷达图
- TechWritingPracticeDemo.vue: 技术写作实践
- TestPyramidDemo.vue: 测试金字塔
- WebSecurityDemo.vue: Web 安全演示

## 文档更新 (7篇)
- code-quality-refactoring.md: 代码质量与重构
- design-patterns.md: 设计模式
- open-source-collaboration.md: 开源协作
- security-thinking.md: 安全思维
- technical-writing.md: 技术写作
- technology-selection.md: 技术选型
- testing-strategies.md: 测试策略

## 其他变更
- 将 browser-as-os.md 内容合并到 computer-networks.md
- 更新 .gitignore 和 theme/index.js
2026-02-24 13:03:21 +08:00

7.2 KiB
Raw Blame History

设计模式

::: tip 前言 为什么你的代码总是"能跑但很乱"? 你可能遇到过这样的情况:需求一变,代码就要大改;想复用一段逻辑,却发现它和其他代码纠缠在一起。设计模式就是前人总结的"代码组织套路",帮你写出灵活、可维护的代码。

本章带你理解最实用的设计模式,不是死记硬背,而是理解"什么场景用什么套路"。 :::

这篇文章会带你学什么?

章节 内容 核心概念
第 1 章 设计模式是什么 模式的本质与分类
第 2 章 创建型模式 如何优雅地创建对象
第 3 章 结构型模式 如何组织代码结构
第 4 章 行为型模式 如何管理对象间的交互

学完本章,你将掌握最常用的设计模式,能在实际项目中识别适用场景并灵活运用。


0. 全景图:设计模式的本质

想象你在学做菜。你可以每次都从零开始摸索,也可以学习经典菜谱——菜谱不会限制你的创造力,反而让你站在前人的肩膀上。设计模式就是编程世界的"经典菜谱"。

::: tip 设计模式的价值

  • 共同语言:说"这里用观察者模式",团队立刻理解你的设计意图
  • 经验复用:不用重新踩前人踩过的坑
  • 灵活扩展:好的模式让代码面对变化时只需小改,而不是大改 :::

通过下面的交互组件,浏览常见设计模式的分类和用途:


1. 创建型模式:如何优雅地创建对象

1.1 单例模式(Singleton

场景:全局只需要一个实例,比如配置管理器、日志记录器、数据库连接池。

class ConfigManager {
  static instance = null

  static getInstance() {
    if (!ConfigManager.instance) {
      ConfigManager.instance = new ConfigManager()
    }
    return ConfigManager.instance
  }

  constructor() {
    this.config = {}
  }
}

// 无论调用多少次,都是同一个实例
const a = ConfigManager.getInstance()
const b = ConfigManager.getInstance()
console.log(a === b) // true

1.2 工厂模式(Factory

场景:根据不同条件创建不同类型的对象,调用方不需要知道具体的创建细节。

function createNotification(type, message) {
  switch (type) {
    case 'email':
      return { send: () => console.log(`发送邮件: ${message}`) }
    case 'sms':
      return { send: () => console.log(`发送短信: ${message}`) }
    case 'push':
      return { send: () => console.log(`推送通知: ${message}`) }
    default:
      throw new Error(`未知通知类型: ${type}`)
  }
}

// 调用方不关心具体实现
const notification = createNotification('email', '你好')
notification.send()

2. 结构型模式:如何组织代码结构

2.1 适配器模式(Adapter

场景:两个接口不兼容,需要一个"转换插头"。比如旧 API 返回的数据格式和新组件期望的格式不一致。

// 旧 API 返回的格式
const oldApi = {
  getUserInfo: () => ({ user_name: '张三', user_age: 25 })
}

// 适配器:转换为新格式
function adaptUser(oldUser) {
  return { name: oldUser.user_name, age: oldUser.user_age }
}

const user = adaptUser(oldApi.getUserInfo())
// { name: '张三', age: 25 }

2.2 装饰器模式(Decorator

场景:在不修改原有代码的前提下,给对象添加新功能。像给手机套壳——手机功能不变,但多了保护。

// 基础日志函数
function log(message) {
  console.log(message)
}

// 装饰:添加时间戳
function withTimestamp(fn) {
  return (message) => fn(`[${new Date().toISOString()}] ${message}`)
}

// 装饰:添加日志级别
function withLevel(fn, level) {
  return (message) => fn(`[${level}] ${message}`)
}

const enhancedLog = withTimestamp(withLevel(log, 'INFO'))
enhancedLog('服务启动成功')
// [2025-01-15T10:30:00.000Z] [INFO] 服务启动成功

3. 行为型模式:如何管理对象间的交互

3.1 观察者模式(Observer

场景:一个对象状态变化时,需要自动通知其他对象。比如用户下单后,需要同时发邮件、扣库存、记日志。

class EventEmitter {
  constructor() {
    this.listeners = {}
  }

  on(event, callback) {
    if (!this.listeners[event]) this.listeners[event] = []
    this.listeners[event].push(callback)
  }

  emit(event, data) {
    (this.listeners[event] || []).forEach(cb => cb(data))
  }
}

const bus = new EventEmitter()
bus.on('order:created', (order) => console.log('发送确认邮件', order.id))
bus.on('order:created', (order) => console.log('扣减库存', order.id))
bus.emit('order:created', { id: 'ORD-001' })

3.2 策略模式(Strategy

场景:同一个操作有多种算法/策略,需要在运行时切换。比如不同的排序方式、不同的价格计算规则。

const pricingStrategies = {
  normal: (price) => price,
  vip: (price) => price * 0.8,
  svip: (price) => price * 0.6
}

function calculatePrice(price, memberLevel) {
  const strategy = pricingStrategies[memberLevel] || pricingStrategies.normal
  return strategy(price)
}

calculatePrice(100, 'vip')  // 80
calculatePrice(100, 'svip') // 60

通过下面的交互组件,动手体验不同设计模式的运行效果:


4. 如何选择设计模式?

你遇到的问题 推荐模式 核心思路
全局只需一个实例 单例 控制实例数量
根据条件创建不同对象 工厂 封装创建逻辑
接口不兼容需要转换 适配器 包装一层转换
动态添加功能 装饰器 层层包装增强
状态变化需通知多方 观察者 发布-订阅解耦
多种算法需运行时切换 策略 将算法封装为对象

::: tip 核心原则 设计模式不是越多越好。过度设计没有设计一样糟糕。只在真正需要灵活性的地方使用模式,简单问题用简单方案。记住 KISS 原则:Keep It Simple, Stupid。 :::


5. 总结

  1. 创建型模式:解决"如何创建对象"的问题,让创建过程更灵活
  2. 结构型模式:解决"如何组织代码"的问题,让结构更清晰
  3. 行为型模式:解决"对象间如何交互"的问题,让协作更松耦合
  4. 灵活运用:根据实际场景选择,不要为了用模式而用模式

::: tip 终极思考 设计模式的本质是管理变化。好的设计让变化的部分容易修改,不变的部分保持稳定。当你写代码时问自己:"如果需求变了,我需要改多少地方?"——如果答案是"很多地方",那可能需要一个设计模式来帮忙了。 :::


延伸阅读

  • 经典书籍:GoF《设计模式:可复用面向对象软件的基础》是设计模式的开山之作。
  • 现代视角JavaScript 中很多模式因为语言特性(闭包、高阶函数)变得更简洁。
  • 实践建议:先理解问题,再考虑模式。不要拿着锤子找钉子。
  • 进阶学习:了解 SOLID 原则,它是设计模式背后的指导思想。