🚀代码整容术:15 大设计模式全解析,JS/TS 程序员逆袭必看!

76 阅读11分钟

"每次Review同事的代码都像在拆炸弹?明明功能实现了,却总在维护时踩坑?90%的前端开发者忽略了设计模式的力量——不是模式没用,而是你用错了姿势!"

痛点共鸣

在快节奏的前端开发中,我们常陷入两大困局:

  1. 野蛮生长:需求倒逼下堆砌面条代码,三个月后连自己都看不懂
  2. 过度设计:生搬硬套Java/C++模式,反而让JavaScript失去灵活性

价值预告

本文将深度解析15种真正适配JavaScript/TypeScript基因的设计模式,每个模式都具备:
✅ 真实业务场景案例
✅ 可复用的TypeScript实现
✅ 避坑指南 + 性能权衡


正文:15大设计模式实战精解

1. 单例模式(Singleton)

痛点场景:全局状态管理(如用户认证信息)
TS实现

class AuthService {
  private static instance: AuthService;
  private constructor() {} // 阻止外部实例化

  public static getInstance(): AuthService {
    if (!AuthService.instance) {
      AuthService.instance = new AuthService();
    }
    return AuthService.instance;
  }

  // 业务方法
  public login(user: string) { 
    console.log(`${user} logged in`);
  }
}

// 使用示例
const auth1 = AuthService.getInstance();
const auth2 = AuthService.getInstance();
console.log(auth1 === auth2); // true

避坑指南
⚠️ 避免在React/Vue组件中滥用,优先考虑Context/Provider


2. 观察者模式(Observer)

痛点场景:实时数据推送(如股票行情、聊天消息)
TS实现

interface Observer {
  update(data: any): void;
}

class StockPublisher {
  private observers: Observer[] = [];
  private price: number = 0;

  public subscribe(observer: Observer) {
    this.observers.push(observer);
  }

  public setPrice(newPrice: number) {
    this.price = newPrice;
    this.notify();
  }

  private notify() {
    this.observers.forEach(obs => obs.update(this.price));
  }
}

// 使用示例
class MobileApp implements Observer {
  update(price: number) {
    console.log(`[MOBILE] Price updated: $${price}`);
  }
}

const publisher = new StockPublisher();
publisher.subscribe(new MobileApp());
publisher.setPrice(150); // [MOBILE] Price updated: $150

性能权衡
🔹 适合低频更新场景
🔹 高频更新建议改用RxJS


3. 策略模式(Strategy)

痛点场景:多算法切换(如支付方式、表单校验)
TS实现

interface ValidationStrategy {
  validate(input: string): boolean;
}

class EmailValidator implements ValidationStrategy {
  validate(input: string) {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input);
  }
}

class PhoneValidator implements ValidationStrategy {
  validate(input: string) {
    return /^1[3-9]\d{9}$/.test(input);
  }
}

class ValidatorContext {
  constructor(private strategy: ValidationStrategy) {}

  setStrategy(strategy: ValidationStrategy) {
    this.strategy = strategy;
  }

  execute(input: string) {
    return this.strategy.validate(input);
  }
}

// 使用示例
const context = new ValidatorContext(new EmailValidator());
console.log(context.execute("test@example.com")); // true

context.setStrategy(new PhoneValidator());
console.log(context.execute("13800138000")); // true

4. 装饰器模式(Decorator)

TS专属优势:语法级支持!
实战场景:API请求日志增强

function LogRequest(target: any, key: string, desc: PropertyDescriptor) {
  const original = desc.value;
  
  desc.value = async function (...args: any[]) {
    console.log(`[REQUEST] ${key} called with:`, args);
    const result = await original.apply(this, args);
    console.log(`[RESPONSE] ${key} returned:`, result);
    return result;
  }
}

class UserService {
  @LogRequest
  async fetchUser(id: number) {
    return { id, name: "John" };
  }
}

// 使用示例
new UserService().fetchUser(1);
// 输出: 
// [REQUEST] fetchUser called with: [1]
// [RESPONSE] fetchUser returned: {id:1, name:"John"}

5. 工厂模式(Factory)

痛点场景:复杂对象创建(如UI组件生成)
TS实现

interface Button {
  render(): string;
}

class PrimaryButton implements Button {
  render() { return "<button class='primary'>Submit</button>"; }
}

class DangerButton implements Button {
  render() { return "<button class='danger'>Delete</button>"; }
}

class ButtonFactory {
  public static createButton(type: "primary" | "danger"): Button {
    switch (type) {
      case "primary": return new PrimaryButton();
      case "danger": return new DangerButton();
      default: throw new Error("Invalid button type");
    }
  }
}

// 使用示例
console.log(ButtonFactory.createButton("danger").render()); 
// <button class='danger'>Delete</button>

6. 适配器模式(Adapter)

痛点场景:整合第三方库时接口不兼容(如新旧支付SDK对接)
TS实现

// 旧版支付宝接口
class AlipayLegacy {
  createPayment(amount: number) {
    return `ALIPAY:${amount}`;
  }
}

// 新版微信支付接口
interface ModernPayment {
  pay(amount: number): string;
}

// 适配器
class PaymentAdapter implements ModernPayment {
  constructor(private legacy: AlipayLegacy) {}

  pay(amount: number) {
    const legacyResult = this.legacy.createPayment(amount);
    return `ADAPTED: ${legacyResult.replace('ALIPAY', 'WECHAT')}`;
  }
}

// 使用示例
const adapter = new PaymentAdapter(new AlipayLegacy());
console.log(adapter.pay(100)); // ADAPTED: WECHAT:100

避坑指南
⚠️ 避免过度适配导致嵌套过深
⚠️ 优先考虑重构接口的可能性


7. 代理模式(Proxy)

痛点场景:API请求缓存/权限控制
TS实现

interface DataService {
  fetchData(): Promise<string>;
}

class RealService implements DataService {
  async fetchData() {
    // 模拟网络请求
    await new Promise(res => setTimeout(res, 1000));
    return "Real data";
  }
}

class CacheProxy implements DataService {
  private cache: string | null = null;
  private realService = new RealService();

  async fetchData() {
    if (!this.cache) {
      this.cache = await this.realService.fetchData();
    }
    return `[CACHED] ${this.cache}`;
  }
}

// 使用示例
const proxy = new CacheProxy();
console.log(await proxy.fetchData()); // [CACHED] Real data (慢)
console.log(await proxy.fetchData()); // [CACHED] Real data (瞬时)

性能权衡
🔹 适合IO密集型操作
🔹 注意缓存失效策略


8. 迭代器模式(Iterator)

痛点场景:统一遍历不同数据结构(如树形菜单/扁平列表)
TS实现

class TreeNode<T> {
  constructor(
    public value: T,
    public children: TreeNode<T>[] = []
  ) {}
}

class TreeIterator<T> {
  private stack: TreeNode<T>[] = [];

  constructor(root: TreeNode<T>) {
    this.stack.push(root);
  }

  next(): T | null {
    if (!this.hasNext()) return null;
    
    const node = this.stack.pop()!;
    // 反向压栈保证顺序
    node.children.slice().reverse().forEach(child => {
      this.stack.push(child);
    });
    
    return node.value;
  }

  hasNext(): boolean {
    return this.stack.length > 0;
  }
}

// 使用示例
const tree = new TreeNode(1, [
  new TreeNode(2, [new TreeNode(4)]),
  new TreeNode(3)
]);

const iterator = new TreeIterator(tree);
while (iterator.hasNext()) {
  console.log(iterator.next()); // 1, 2, 4, 3
}

9. 状态模式(State)

痛点场景:复杂状态流转(如订单生命周期)
TS实现

interface OrderState {
  next(order: Order): void;
  prev(order: Order): void;
}

class DraftState implements OrderState {
  next(order: Order) {
    order.setState(new PaidState());
  }
  prev() { /* 首个状态 */ }
}

class PaidState implements OrderState {
  next(order: Order) {
    order.setState(new ShippedState());
  }
  prev(order: Order) {
    order.setState(new DraftState());
  }
}

class ShippedState implements OrderState {
  next(order: Order) {
    order.setState(new CompletedState());
  }
  prev(order: Order) {
    order.setState(new PaidState());
  }
}

class Order {
  private state: OrderState = new DraftState();

  setState(state: OrderState) {
    this.state = state;
  }

  proceed() {
    this.state.next(this);
  }

  rollback() {
    this.state.prev(this);
  }
}

// 使用示例
const order = new Order();
order.proceed(); // Draft -> Paid
order.proceed(); // Paid -> Shipped
order.rollback(); // Shipped -> Paid

10. 模块模式(Module)

现代方案:ES Module + TypeScript类型增强
实战场景:SDK封装与类型导出

// payment.ts
interface PaymentConfig {
  apiKey: string;
  timeout?: number;
}

export function createPayment(config: PaymentConfig) {
  let balance = 0;

  return {
    deposit(amount: number) {
      balance += amount;
    },
    pay(amount: number) {
      if (balance >= amount) {
        balance -= amount;
        return `Paid ${amount} using ${config.apiKey}`;
      }
      throw new Error("Insufficient balance");
    }
  };
}

// 使用示例
import { createPayment } from './payment';

const payment = createPayment({ apiKey: 'KEY_123' });
payment.deposit(500);
console.log(payment.pay(300)); // Paid 300 using KEY_123

11. 发布订阅模式(Pub/Sub)

爆款场景:百万级在线聊天系统
TS黑科技:类型安全事件总线

type EventMap = {
  message: [string, number];
  userJoin: [string];
};

class EventBus {
  private listeners: { [K in keyof EventMap]?: Function[] } = {};

  on<K extends keyof EventMap>(event: K, listener: (...args: EventMap[K]) => void) {
    (this.listeners[event] ||= []).push(listener);
  }

  emit<K extends keyof EventMap>(event: K, ...args: EventMap[K]) {
    this.listeners[event]?.forEach(fn => fn(...args));
  }
}

// 使用示例
const bus = new EventBus();
bus.on("message", (text, timestamp) => {
  console.log(`[${timestamp}] ${text}`);
});
bus.emit("message", "Hello TS!", Date.now()); // [165000000] Hello TS!

12. 职责链模式(Chain of Responsibility)

高薪必备:中间件系统(如Express/Koa)
TS实现

interface Handler {
  setNext(handler: Handler): Handler;
  handle(request: string): string | null;
}

abstract class AbstractHandler implements Handler {
  private nextHandler: Handler | null = null;

  setNext(handler: Handler): Handler {
    this.nextHandler = handler;
    return handler;
  }

  handle(request: string): string | null {
    return this.nextHandler?.handle(request) ?? null;
  }
}

class AuthHandler extends AbstractHandler {
  handle(request: string) {
    if (request.includes("token=valid")) return super.handle(request);
    return "401 Unauthorized";
  }
}

class CacheHandler extends AbstractHandler {
  handle(request: string) {
    if (request.includes("no-cache")) return super.handle(request);
    return "304 Not Modified";
  }
}

// 使用示例
const chain = new AuthHandler();
chain.setNext(new CacheHandler());
console.log(chain.handle("token=valid&no-cache")); // null (通过)
console.log(chain.handle("token=invalid")); // 401 Unauthorized

13. 命令模式(Command)

跳槽神器:实现撤销/重做功能(如在线设计工具)
TS实现

interface Command {
  execute(): void;
  undo(): void;
}

class Canvas {
  public content: string[] = [];
  
  addElement(element: string) {
    this.content.push(element);
  }
  
  removeLast() {
    this.content.pop();
  }
}

class AddCommand implements Command {
  constructor(
    private canvas: Canvas,
    private element: string
  ) {}

  execute() {
    this.canvas.addElement(this.element);
  }

  undo() {
    this.canvas.removeLast();
  }
}

class CommandHistory {
  private history: Command[] = [];

  execute(command: Command) {
    command.execute();
    this.history.push(command);
  }

  undo() {
    const command = this.history.pop();
    command?.undo();
  }
}

// 使用示例
const canvas = new Canvas();
const history = new CommandHistory();

history.execute(new AddCommand(canvas, "Button"));
history.execute(new AddCommand(canvas, "Input"));
console.log(canvas.content); // ["Button", "Input"]

history.undo();
console.log(canvas.content); // ["Button"]

14. 享元模式(Flyweight)

大厂必考:万级粒子系统性能优化
TS黑科技

type ParticleType = {
  texture: string;
  color: string;
};

class ParticleFactory {
  private types: Record<string, ParticleType> = {};

  getType(texture: string, color: string): ParticleType {
    const key = `${texture}|${color}`;
    if (!this.types[key]) {
      console.log(`Creating new type: ${key}`);
      this.types[key] = { texture, color };
    }
    return this.types[key];
  }
}

class Particle {
  constructor(
    private type: ParticleType,
    public x: number,
    public y: number
  ) {}

  render() {
    console.log(`Rendering ${type.texture} at (${x},${y})`);
  }
}

// 使用示例
const factory = new ParticleFactory();
const particles: Particle[] = [];

// 创建10000个粒子,只有2种类型
for (let i = 0; i < 5000; i++) {
  particles.push(new Particle(factory.getType("star", "yellow"), Math.random(), Math.random()));
  particles.push(new Particle(factory.getType("circle", "red"), Math.random(), Math.random()));
}
// 输出: "Creating new type: star|yellow" 和 "Creating new type: circle|red" 各一次

15. 模板方法模式(Template Method)

架构师思维:AI工作流引擎设计
TS实现

abstract class AIPipeline {
  // 模板方法
  public run() {
    this.loadData();
    this.preprocess();
    this.train();
    this.evaluate();
    this.deploy();
  }

  protected abstract loadData(): void;
  protected abstract preprocess(): void;
  
  protected train() {
    console.log("Default training...");
  }

  protected evaluate() {
    console.log("Default evaluation...");
  }

  protected deploy() {
    console.log("Deploying to cloud...");
  }
}

class ImagePipeline extends AIPipeline {
  protected loadData() {
    console.log("Loading image dataset...");
  }

  protected preprocess() {
    console.log("Resizing images to 224x224...");
  }

  protected train() {
    console.log("Fine-tuning ResNet50...");
  }
}

// 使用示例
new ImagePipeline().run();
/* 输出:
Loading image dataset...
Resizing images to 224x224...
Fine-tuning ResNet50...
Default evaluation...
Deploying to cloud...
*/

15大设计模式终极对照表(含适用场景+实战案例)

设计模式适用场景案例1案例2案例3
单例模式全局唯一实例需求用户认证服务应用配置管理器日志记录器
观察者模式实时数据联动更新股票行情推送系统表单字段联动验证多人协作文档同步
策略模式多算法动态切换支付方式选择(微信/支付宝)数据校验规则库地图导航路径计算
装饰器模式功能动态增强API请求日志记录用户权限校验拦截性能监控埋点
工厂模式复杂对象创建解耦UI组件库生成器游戏角色生成系统跨平台文件读写适配器
适配器模式接口兼容转换新旧支付SDK对接第三方地图插件封装遗留系统API现代化改造
代理模式访问控制/缓存优化API请求缓存层图片懒加载预处理器敏感操作权限拦截器
迭代器模式统一数据结构遍历树形菜单递归遍历多源数据合并查询文件目录深度扫描
状态模式复杂状态流转管理订单生命周期管理游戏角色行为状态机工作流审批系统
模块模式代码组织与封装SDK工具库开发私有方法隔离实现插件化架构核心
发布订阅模式多对多事件通信聊天室消息广播微服务间事件驱动通信实时数据仪表盘更新
职责链模式请求流水线处理中间件权限校验链错误处理责任链路电商优惠券规则引擎
命令模式操作封装与撤销/重做图形编辑器历史记录智能家居遥控系统自动化测试脚本执行器
享元模式海量相似对象性能优化粒子系统渲染优化表格数据内存管理游戏地图瓦片加载器
模板方法模式流程标准化扩展AI训练流水线数据导出通用框架自动化部署工作流

深度案例解析(每个模式精选3个场景)

1. 单例模式

  • 用户认证服务:全局管理登录状态,避免重复实例化
  • 应用配置管理器:统一读取.env配置,线程安全
  • 日志记录器:多模块共享写日志文件,防IO冲突

2. 观察者模式

  • 股票行情推送:1个数据源 → 1000个客户端实时更新
  • 表单字段联动:地址选择 → 自动更新快递费用计算
  • 文档协同编辑:用户A编辑段落 → 用户B/C实时高亮显示

3. 策略模式

  • 支付方式切换:用户选择微信 → 调用微信SDK策略
  • 数据校验规则:邮箱校验 → 手机号校验 → 身份证校验
  • 导航路径计算:驾车策略/步行策略/公交策略实时切换

4. 装饰器模式

  • API日志增强:自动记录请求参数+响应时间+错误码
  • 权限校验拦截:@AdminRequired装饰器自动验证角色
  • 性能监控埋点:@Benchmark自动记录函数执行耗时

5. 工厂模式

  • UI组件生成:createComponent('button', {type: 'primary'})
  • 游戏角色生成:spawnEnemy('boss') vs spawnEnemy('minion')
  • 文件系统适配:createFileSystem('s3') vs createFileSystem('local')

6. 适配器模式

  • 支付SDK兼容:将支付宝接口适配成微信支付调用格式
  • 地图插件封装:将Leaflet API转换成高德地图调用规范
  • 遗留系统改造:将COBOL数据接口适配RESTful JSON格式

7. 代理模式

  • API请求缓存:首次请求DB → 后续请求内存缓存
  • 图片懒加载:滚动时加载真实图片 → 默认显示占位图
  • 敏感操作拦截:删除操作 → 代理弹窗确认二次验证

8. 迭代器模式

  • 树形菜单遍历:深度优先遍历组织架构树
  • 多源数据合并:循环遍历SQL+Redis+MongoDB混合数据
  • 文件目录扫描:递归遍历node_modules依赖树

9. 状态模式

  • 订单状态机:draft → paid → shipped → completed
  • 游戏角色行为:idle → run → attack → die状态切换
  • 工作流审批:pending → approved → rejected状态流转

10. 模块模式

  • SDK开发:axios.create()封装不同实例配置
  • 私有方法隔离:内部实现细节隐藏,暴露简洁API
  • 插件化架构:core.install(plugin)动态扩展功能

11. 发布订阅模式

  • 聊天室广播:用户发言 → 所有在线成员接收消息
  • 微服务通信:订单服务 → 通知库存服务扣减库存
  • 实时仪表盘:数据库变更 → 大屏图表实时刷新

12. 职责链模式

  • 中间件校验链:请求 → 认证 → 授权 → 限流 → 业务处理
  • 错误处理链路:404错误 → 日志记录 → 邮件通知 → 降级处理
  • 优惠券规则引擎:满减券 → 折扣券 → 运费券顺序应用

13. 命令模式

  • 编辑器历史记录:文字操作支持50级undo/redo
  • 智能家居遥控:一键执行"离家模式"(关灯+锁门+关空调)
  • 自动化测试:封装click→input→assert操作为可回放命令

14. 享元模式

  • 粒子系统优化:10万颗星星共享1种纹理+颜色配置
  • 表格内存管理:渲染10万行数据只创建20种单元格类型
  • 游戏地图加载:草原/沙漠/雪地纹理各复用1000+次

15. 模板方法模式

  • AI训练流水线:数据加载 → 预处理 → 训练 → 评估标准化流程
  • 数据导出框架:查询 → 格式化 → 压缩 → 上传通用模板
  • 自动化部署:代码拉取 → 构建 → 测试 → 发布标准流程

设计模式避坑指南


高频陷阱与规避方案

设计模式致命陷阱规避方案
单例模式内存泄漏提供destroy()方法,用WeakMap存储实例
观察者模式循环触发事件使用异步队列(如setTimeout),添加事件ID防重
策略模式策略数量爆炸用配置文件动态加载策略,限制策略总数≤20
装饰器模式多层嵌套性能劣化限制装饰层级≤3层,复杂场景改用组合模式
代理模式缓存穿透添加空值缓存标记,设置缓存失效时间
发布订阅消息丢失引入持久化队列(如Redis),实现ACK确认机制
享元模式共享状态污染深拷贝共享对象,使用不可变数据结构

三大黄金定律

  1. 5行代码原则

    // 坏味道:用工厂模式创建简单对象
    class BadFactory {
      createConfig() { return { theme: 'light' } } // ❌ 过度设计
    }
    
    // 优化方案
    const config = { theme: 'light' }; // ✅ 直接创建
    
  2. 性能红线

    模式临界点替代方案
    装饰器链>5层组合函数
    代理拦截>1000次/秒原生方法
    观察者通知>500消息/秒批量更新机制
  3. TS类型安全屏障

    // 用类型体操防止模式滥用
    type ForbidSingleton<T> = T extends { new(): infer U } 
      ? "Use dependency injection instead!" 
      : U;
    

结语:设计模式的终极哲学

模式是路标,不是牢笼

  • 当你的代码需要3层注释才能解释设计模式的应用时,你已经误入歧途
  • 真正的架构师能在模式简洁间精准取舍
  • 记住:删除代码比编写代码更需要勇气

资源推荐

  1. [TypeScript设计模式实战 - GitHub](github.com/torokmark/d…)
    • 包含23个模式的完整实现
    • 配套性能测试用例
  2. [JavaScript设计模式精髓 - 掘金小册](juejin.cn/book/684473…)
    • 结合Vue/React真实案例
    • 内存泄漏检测指南
  3. 设计模式调试工具
    npx design-pattern-lint <your_file.ts>
    

最后忠告
“最好的设计模式,是让你的代码在半年后还能被新手读懂——这才是真正的技术深度。”