design-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Design Patterns

Design Patterns

Overview

概述

Reusable solutions to common software design problems. Understanding patterns helps you communicate design ideas effectively and avoid reinventing the wheel.

针对常见软件设计问题的可复用解决方案。理解设计模式有助于你高效传达设计思路,避免重复造轮子。

Creational Patterns

Creational Patterns

Factory Method

Factory Method

Purpose: Create objects without specifying exact class
typescript
// Abstract factory
interface PaymentProcessor {
  process(amount: number): Promise<Result>;
}

class StripeProcessor implements PaymentProcessor { /* ... */ }
class PayPalProcessor implements PaymentProcessor { /* ... */ }

function createProcessor(type: string): PaymentProcessor {
  switch (type) {
    case 'stripe': return new StripeProcessor();
    case 'paypal': return new PayPalProcessor();
    default: throw new Error(`Unknown processor: ${type}`);
  }
}
用途:无需指定具体类即可创建对象
typescript
// Abstract factory
interface PaymentProcessor {
  process(amount: number): Promise<Result>;
}

class StripeProcessor implements PaymentProcessor { /* ... */ }
class PayPalProcessor implements PaymentProcessor { /* ... */ }

function createProcessor(type: string): PaymentProcessor {
  switch (type) {
    case 'stripe': return new StripeProcessor();
    case 'paypal': return new PayPalProcessor();
    default: throw new Error(`Unknown processor: ${type}`);
  }
}

Builder

Builder

Purpose: Construct complex objects step by step
typescript
class QueryBuilder {
  private query: Query = {};

  select(...fields: string[]) {
    this.query.fields = fields;
    return this;
  }

  from(table: string) {
    this.query.table = table;
    return this;
  }

  where(condition: Condition) {
    this.query.conditions ??= [];
    this.query.conditions.push(condition);
    return this;
  }

  build(): string {
    return this.compile(this.query);
  }
}

// Usage
const sql = new QueryBuilder()
  .select('id', 'name')
  .from('users')
  .where({ age: { gte: 18 } })
  .build();
用途:逐步构建复杂对象
typescript
class QueryBuilder {
  private query: Query = {};

  select(...fields: string[]) {
    this.query.fields = fields;
    return this;
  }

  from(table: string) {
    this.query.table = table;
    return this;
  }

  where(condition: Condition) {
    this.query.conditions ??= [];
    this.query.conditions.push(condition);
    return this;
  }

  build(): string {
    return this.compile(this.query);
  }
}

// Usage
const sql = new QueryBuilder()
  .select('id', 'name')
  .from('users')
  .where({ age: { gte: 18 } })
  .build();

Singleton

Singleton

Purpose: Ensure single instance (use sparingly)
typescript
// Modern approach: module-level instance
// database.ts
class Database {
  private constructor() {}

  private static instance: Database;

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

// Better: Dependency injection
class UserService {
  constructor(private db: Database) {}
}

用途:确保单一实例(谨慎使用)
typescript
// Modern approach: module-level instance
// database.ts
class Database {
  private constructor() {}

  private static instance: Database;

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

// Better: Dependency injection
class UserService {
  constructor(private db: Database) {}
}

Structural Patterns

Structural Patterns

Adapter

Adapter

Purpose: Make incompatible interfaces work together
typescript
// Legacy API returns XML
interface LegacyAPI {
  getDataXML(): string;
}

// New code expects JSON
interface ModernAPI {
  getData(): object;
}

class APIAdapter implements ModernAPI {
  constructor(private legacy: LegacyAPI) {}

  getData(): object {
    const xml = this.legacy.getDataXML();
    return this.parseXML(xml);
  }

  private parseXML(xml: string): object {
    // Convert XML to object
  }
}
用途:让不兼容的接口协同工作
typescript
// Legacy API returns XML
interface LegacyAPI {
  getDataXML(): string;
}

// New code expects JSON
interface ModernAPI {
  getData(): object;
}

class APIAdapter implements ModernAPI {
  constructor(private legacy: LegacyAPI) {}

  getData(): object {
    const xml = this.legacy.getDataXML();
    return this.parseXML(xml);
  }

  private parseXML(xml: string): object {
    // Convert XML to object
  }
}

Decorator

Decorator

Purpose: Add behavior without modifying original
typescript
// Base interface
interface DataSource {
  read(): string;
  write(data: string): void;
}

// Decorator adds encryption
class EncryptedDataSource implements DataSource {
  constructor(private wrapped: DataSource) {}

  read(): string {
    return this.decrypt(this.wrapped.read());
  }

  write(data: string): void {
    this.wrapped.write(this.encrypt(data));
  }
}

// Decorator adds compression
class CompressedDataSource implements DataSource {
  constructor(private wrapped: DataSource) {}
  // Similar pattern...
}

// Compose decorators
const source = new EncryptedDataSource(
  new CompressedDataSource(
    new FileDataSource('data.txt')
  )
);
用途:在不修改原对象的前提下添加行为
typescript
// Base interface
interface DataSource {
  read(): string;
  write(data: string): void;
}

// Decorator adds encryption
class EncryptedDataSource implements DataSource {
  constructor(private wrapped: DataSource) {}

  read(): string {
    return this.decrypt(this.wrapped.read());
  }

  write(data: string): void {
    this.wrapped.write(this.encrypt(data));
  }
}

// Decorator adds compression
class CompressedDataSource implements DataSource {
  constructor(private wrapped: DataSource) {}
  // Similar pattern...
}

// Compose decorators
const source = new EncryptedDataSource(
  new CompressedDataSource(
    new FileDataSource('data.txt')
  )
);

Facade

Facade

Purpose: Simplify complex subsystem
typescript
// Complex subsystems
class VideoConverter { /* ... */ }
class AudioExtractor { /* ... */ }
class BitrateCalculator { /* ... */ }
class CodecFactory { /* ... */ }

// Simple facade
class VideoExporter {
  export(video: Video, format: Format): File {
    const codec = CodecFactory.getCodec(format);
    const bitrate = BitrateCalculator.optimal(video);
    const converter = new VideoConverter(codec, bitrate);
    const audio = AudioExtractor.extract(video);
    return converter.convert(video, audio);
  }
}

// Client only needs facade
const exporter = new VideoExporter();
const mp4 = exporter.export(video, 'mp4');
用途:简化复杂子系统
typescript
// Complex subsystems
class VideoConverter { /* ... */ }
class AudioExtractor { /* ... */ }
class BitrateCalculator { /* ... */ }
class CodecFactory { /* ... */ }

// Simple facade
class VideoExporter {
  export(video: Video, format: Format): File {
    const codec = CodecFactory.getCodec(format);
    const bitrate = BitrateCalculator.optimal(video);
    const converter = new VideoConverter(codec, bitrate);
    const audio = AudioExtractor.extract(video);
    return converter.convert(video, audio);
  }
}

// Client only needs facade
const exporter = new VideoExporter();
const mp4 = exporter.export(video, 'mp4');

Proxy

Proxy

Purpose: Control access to object
typescript
// Virtual proxy for lazy loading
class ImageProxy implements Image {
  private realImage: RealImage | null = null;

  constructor(private filename: string) {}

  display(): void {
    if (!this.realImage) {
      this.realImage = new RealImage(this.filename); // Expensive
    }
    this.realImage.display();
  }
}

// Protection proxy
class SecureDocumentProxy implements Document {
  constructor(
    private doc: Document,
    private user: User
  ) {}

  read(): string {
    if (!this.user.hasPermission('read')) {
      throw new Error('Access denied');
    }
    return this.doc.read();
  }
}

用途:控制对对象的访问
typescript
// Virtual proxy for lazy loading
class ImageProxy implements Image {
  private realImage: RealImage | null = null;

  constructor(private filename: string) {}

  display(): void {
    if (!this.realImage) {
      this.realImage = new RealImage(this.filename); // Expensive
    }
    this.realImage.display();
  }
}

// Protection proxy
class SecureDocumentProxy implements Document {
  constructor(
    private doc: Document,
    private user: User
  ) {}

  read(): string {
    if (!this.user.hasPermission('read')) {
      throw new Error('Access denied');
    }
    return this.doc.read();
  }
}

Behavioral Patterns

Behavioral Patterns

Observer

Observer

Purpose: Notify dependents of state changes
typescript
class EventEmitter<T extends Record<string, unknown>> {
  private listeners = new Map<keyof T, Set<Function>>();

  on<K extends keyof T>(event: K, callback: (data: T[K]) => void) {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, new Set());
    }
    this.listeners.get(event)!.add(callback);

    // Return unsubscribe function
    return () => this.listeners.get(event)?.delete(callback);
  }

  emit<K extends keyof T>(event: K, data: T[K]) {
    this.listeners.get(event)?.forEach(cb => cb(data));
  }
}

// Usage
interface Events {
  userCreated: User;
  orderPlaced: Order;
}

const emitter = new EventEmitter<Events>();
emitter.on('userCreated', user => sendWelcomeEmail(user));
用途:状态变化时通知依赖方
typescript
class EventEmitter<T extends Record<string, unknown>> {
  private listeners = new Map<keyof T, Set<Function>>();

  on<K extends keyof T>(event: K, callback: (data: T[K]) => void) {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, new Set());
    }
    this.listeners.get(event)!.add(callback);

    // Return unsubscribe function
    return () => this.listeners.get(event)?.delete(callback);
  }

  emit<K extends keyof T>(event: K, data: T[K]) {
    this.listeners.get(event)?.forEach(cb => cb(data));
  }
}

// Usage
interface Events {
  userCreated: User;
  orderPlaced: Order;
}

const emitter = new EventEmitter<Events>();
emitter.on('userCreated', user => sendWelcomeEmail(user));

Strategy

Strategy

Purpose: Interchange algorithms at runtime
typescript
interface CompressionStrategy {
  compress(data: Buffer): Buffer;
}

class ZipCompression implements CompressionStrategy {
  compress(data: Buffer): Buffer { /* ... */ }
}

class GzipCompression implements CompressionStrategy {
  compress(data: Buffer): Buffer { /* ... */ }
}

class FileCompressor {
  constructor(private strategy: CompressionStrategy) {}

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

  compress(file: File): Buffer {
    return this.strategy.compress(file.data);
  }
}
用途:运行时切换算法
typescript
interface CompressionStrategy {
  compress(data: Buffer): Buffer;
}

class ZipCompression implements CompressionStrategy {
  compress(data: Buffer): Buffer { /* ... */ }
}

class GzipCompression implements CompressionStrategy {
  compress(data: Buffer): Buffer { /* ... */ }
}

class FileCompressor {
  constructor(private strategy: CompressionStrategy) {}

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

  compress(file: File): Buffer {
    return this.strategy.compress(file.data);
  }
}

Command

Command

Purpose: Encapsulate actions as objects
typescript
interface Command {
  execute(): void;
  undo(): void;
}

class MoveCommand implements Command {
  private previousPosition: Position;

  constructor(
    private object: GameObject,
    private newPosition: Position
  ) {}

  execute() {
    this.previousPosition = this.object.position;
    this.object.position = this.newPosition;
  }

  undo() {
    this.object.position = this.previousPosition;
  }
}

class CommandHistory {
  private history: Command[] = [];
  private current = -1;

  execute(command: Command) {
    command.execute();
    this.history = this.history.slice(0, this.current + 1);
    this.history.push(command);
    this.current++;
  }

  undo() {
    if (this.current >= 0) {
      this.history[this.current].undo();
      this.current--;
    }
  }

  redo() {
    if (this.current < this.history.length - 1) {
      this.current++;
      this.history[this.current].execute();
    }
  }
}
用途:将操作封装为对象
typescript
interface Command {
  execute(): void;
  undo(): void;
}

class MoveCommand implements Command {
  private previousPosition: Position;

  constructor(
    private object: GameObject,
    private newPosition: Position
  ) {}

  execute() {
    this.previousPosition = this.object.position;
    this.object.position = this.newPosition;
  }

  undo() {
    this.object.position = this.previousPosition;
  }
}

class CommandHistory {
  private history: Command[] = [];
  private current = -1;

  execute(command: Command) {
    command.execute();
    this.history = this.history.slice(0, this.current + 1);
    this.history.push(command);
    this.current++;
  }

  undo() {
    if (this.current >= 0) {
      this.history[this.current].undo();
      this.current--;
    }
  }

  redo() {
    if (this.current < this.history.length - 1) {
      this.current++;
      this.history[this.current].execute();
    }
  }
}

State

State

Purpose: Change behavior based on state
typescript
interface State {
  handle(context: Context): void;
}

class DraftState implements State {
  handle(context: Context) {
    console.log('Document is draft');
    // Can edit, save, submit for review
  }
}

class ReviewState implements State {
  handle(context: Context) {
    console.log('Document under review');
    // Can approve or reject
  }
}

class PublishedState implements State {
  handle(context: Context) {
    console.log('Document is published');
    // Read-only, can unpublish
  }
}

class Document {
  private state: State = new DraftState();

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

  handle() {
    this.state.handle(this);
  }
}

用途:根据状态改变行为
typescript
interface State {
  handle(context: Context): void;
}

class DraftState implements State {
  handle(context: Context) {
    console.log('Document is draft');
    // Can edit, save, submit for review
  }
}

class ReviewState implements State {
  handle(context: Context) {
    console.log('Document under review');
    // Can approve or reject
  }
}

class PublishedState implements State {
  handle(context: Context) {
    console.log('Document is published');
    // Read-only, can unpublish
  }
}

class Document {
  private state: State = new DraftState();

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

  handle() {
    this.state.handle(this);
  }
}

Functional Patterns

Functional Patterns

Monad (Result/Option)

Monad (Result/Option)

typescript
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };

function map<T, U, E>(
  result: Result<T, E>,
  fn: (value: T) => U
): Result<U, E> {
  return result.ok
    ? { ok: true, value: fn(result.value) }
    : result;
}

function flatMap<T, U, E>(
  result: Result<T, E>,
  fn: (value: T) => Result<U, E>
): Result<U, E> {
  return result.ok ? fn(result.value) : result;
}

// Usage - compose operations safely
const result = pipe(
  parseJSON(input),
  flatMap(validate),
  flatMap(save),
  map(formatResponse)
);
typescript
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };

function map<T, U, E>(
  result: Result<T, E>,
  fn: (value: T) => U
): Result<U, E> {
  return result.ok
    ? { ok: true, value: fn(result.value) }
    : result;
}

function flatMap<T, U, E>(
  result: Result<T, E>,
  fn: (value: T) => Result<U, E>
): Result<U, E> {
  return result.ok ? fn(result.value) : result;
}

// Usage - compose operations safely
const result = pipe(
  parseJSON(input),
  flatMap(validate),
  flatMap(save),
  map(formatResponse)
);

Pipeline / Middleware

Pipeline / Middleware

typescript
type Middleware<T> = (context: T, next: () => Promise<void>) => Promise<void>;

class Pipeline<T> {
  private middlewares: Middleware<T>[] = [];

  use(middleware: Middleware<T>) {
    this.middlewares.push(middleware);
    return this;
  }

  async execute(context: T) {
    let index = 0;

    const next = async (): Promise<void> => {
      if (index < this.middlewares.length) {
        const middleware = this.middlewares[index++];
        await middleware(context, next);
      }
    };

    await next();
  }
}

typescript
type Middleware<T> = (context: T, next: () => Promise<void>) => Promise<void>;

class Pipeline<T> {
  private middlewares: Middleware<T>[] = [];

  use(middleware: Middleware<T>) {
    this.middlewares.push(middleware);
    return this;
  }

  async execute(context: T) {
    let index = 0;

    const next = async (): Promise<void> => {
      if (index < this.middlewares.length) {
        const middleware = this.middlewares[index++];
        await middleware(context, next);
      }
    };

    await next();
  }
}

Anti-Patterns to Avoid

需避免的反模式

Anti-PatternProblemSolution
God ObjectOne class does everythingSplit into focused classes
Spaghetti CodeTangled dependenciesApply SRP, use modules
Golden HammerUsing one pattern everywhereChoose right pattern per problem
Premature OptimizationOptimizing before measuringProfile first, then optimize

反模式问题解决方案
上帝对象一个类包揽所有功能拆分为职责单一的类
意大利面条式代码依赖关系混乱遵循单一职责原则,使用模块化
万能锤子无论什么问题都用同一种模式根据具体问题选择合适的模式
过早优化在未做度量前就进行优化先做性能分析,再进行优化

Decision Guide

决策指南

Need to create objects?
├── Complex construction → Builder
├── Family of related objects → Abstract Factory
├── Subclass decides type → Factory Method
└── Single instance → Singleton (rarely)

Need to structure objects?
├── Make incompatible interfaces work → Adapter
├── Add behavior dynamically → Decorator
├── Simplify complex system → Facade
└── Control access → Proxy

Need to manage behavior?
├── Notify on state change → Observer
├── Swap algorithms → Strategy
├── Encapsulate actions → Command
└── State-dependent behavior → State
需要创建对象?
├── 复杂构造过程 → Builder
├── 相关对象家族 → Abstract Factory
├── 由子类决定类型 → Factory Method
└── 单一实例 → Singleton(极少使用)

需要组织对象结构?
├── 让不兼容的接口协同工作 → Adapter
├── 动态添加行为 → Decorator
├── 简化复杂系统 → Facade
└── 控制对象访问 → Proxy

需要管理行为?
├── 状态变化时通知依赖方 → Observer
├── 运行时切换算法 → Strategy
├── 封装操作作为对象 → Command
└── 基于状态改变行为 → State

Related Skills

相关技能

  • [[architecture-patterns]] - Higher-level patterns
  • [[code-quality]] - When to apply patterns
  • [[refactoring]] - Introducing patterns to existing code
  • [[architecture-patterns]] - 更高层级的模式
  • [[code-quality]] - 模式的适用场景
  • [[refactoring]] - 为现有代码引入模式