正在加载,请稍候…

Gang of Four Design Patterns in TypeScript

Implement classic GoF design patterns in TypeScript. Learn Factory, Observer, Strategy, Decorator, and Command patterns with practical examples.

Gang of Four Design Patterns in TypeScript

Design patterns are proven solutions to recurring software design problems.

Factory Pattern

interface Button {
  render(): string;
  onClick(): void;
}

class WindowsButton implements Button {
  render() { return '<button class="windows">Click</button>'; }
  onClick() { console.log('Windows button clicked'); }
}

class MacButton implements Button {
  render() { return '<button class="mac">Click</button>'; }
  onClick() { console.log('Mac button clicked'); }
}

abstract class Dialog {
  abstract createButton(): Button;

  render() {
    const button = this.createButton();
    return button.render();
  }
}

class WindowsDialog extends Dialog {
  createButton() { return new WindowsButton(); }
}

class MacDialog extends Dialog {
  createButton() { return new MacButton(); }
}

Observer Pattern

interface Observer<T> {
  update(event: T): void;
}

class EventEmitter<T> {
  private observers = new Map<string, Set<Observer<T>>>();

  subscribe(event: string, observer: Observer<T>) {
    if (!this.observers.has(event)) {
      this.observers.set(event, new Set());
    }
    this.observers.get(event)!.add(observer);
  }

  unsubscribe(event: string, observer: Observer<T>) {
    this.observers.get(event)?.delete(observer);
  }

  emit(event: string, data: T) {
    this.observers.get(event)?.forEach(obs => obs.update(data));
  }
}

// Usage
const emitter = new EventEmitter<{ userId: string }>();
emitter.subscribe('user:login', {
  update: ({ userId }) => console.log(`User ${userId} logged in`),
});

Strategy Pattern

interface SortStrategy<T> {
  sort(data: T[]): T[];
}

class QuickSort<T> implements SortStrategy<T> {
  sort(data: T[]): T[] {
    // Quick sort implementation
    return [...data].sort();
  }
}

class BubbleSort<T> implements SortStrategy<T> {
  sort(data: T[]): T[] {
    // Bubble sort implementation
    return [...data].sort();
  }
}

class Sorter<T> {
  constructor(private strategy: SortStrategy<T>) {}

  setStrategy(strategy: SortStrategy<T>) {
    this.strategy = strategy;
  }

  sort(data: T[]): T[] {
    return this.strategy.sort(data);
  }
}

Decorator Pattern

interface Logger {
  log(message: string): void;
}

class ConsoleLogger implements Logger {
  log(message: string) { console.log(message); }
}

abstract class LoggerDecorator implements Logger {
  constructor(protected logger: Logger) {}
  abstract log(message: string): void;
}

class TimestampDecorator extends LoggerDecorator {
  log(message: string) {
    this.logger.log(`[${new Date().toISOString()}] ${message}`);
  }
}

class PrefixDecorator extends LoggerDecorator {
  constructor(logger: Logger, private prefix: string) { super(logger); }
  log(message: string) {
    this.logger.log(`${this.prefix}: ${message}`);
  }
}

// Usage
const logger = new PrefixDecorator(
  new TimestampDecorator(new ConsoleLogger()),
  'APP'
);
logger.log('Server started');
// APP: [2025-01-01T00:00:00.000Z] Server started

Command Pattern

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

class TextEditor {
  private content = '';
  private history: Command[] = [];

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

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

  getContent() { return this.content; }
  setContent(c: string) { this.content = c; }
}

class InsertTextCommand implements Command {
  private previousContent: string;

  constructor(private editor: TextEditor, private text: string) {
    this.previousContent = editor.getContent();
  }

  execute() {
    this.editor.setContent(this.editor.getContent() + this.text);
  }

  undo() {
    this.editor.setContent(this.previousContent);
  }
}

These patterns solve real architectural challenges encountered in professional software development.