面试中经常被问到的设计模式

89 阅读1分钟

单例模式 (Singleton

单例:此模式涉及创建一个只能实例化一次的类,并提供对该实例的单点访问。 这对于管理全局状态或资源很有用。

class Database {
  private static instance: Database;

  private constructor() {}

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

    return Database.instance;
  }

  public query(sql: string): any[] {
    // ...
  }
}

const db = Database.getInstance();

工厂模式 (Factory

工厂:此模式涉及创建一个类,该类负责根据某些输入或配置创建其他类的实例。 这对于创建需要复杂初始化或配置的对象很有用。

interface Animal {
  speak(): void;
}

class Dog implements Animal {
  public speak() {
    console.log("Woof!");
  }
}

class Cat implements Animal {
  public speak() {
    console.log("Meow!");
  }
}

class AnimalFactory {
  public createAnimal(type: "dog" | "cat"): Animal {
    switch (type) {
      case "dog":
        return new Dog();
      case "cat":
        return new Cat();
      default:
        throw new Error(`Invalid animal type: ${type}`);
    }
  }
}

const factory = new AnimalFactory();
const dog = factory.createAnimal("dog");
const cat = factory.createAnimal("cat");


装饰器模式

装饰器模式是一种设计模式,它允许在运行时动态地给一个对象添加一些额外的行为或责任,而不会影响到其他对象。在 TypeScript 中,装饰器是一种特殊的声明,它可以附加到类声明、方法、属性或参数上,并提供了一种在编译时修改类或方法的声明的方式。

以下是一个使用 TypeScript 实现装饰器模式的例子:

// 定义一个接口,表示组件的基本行为
interface Component {
  operation(): string;
}

// 实现组件的具体行为
class ConcreteComponent implements Component {
  public operation(): string {
    return "ConcreteComponent";
  }
}

// 定义一个装饰器基类,用于维护对被装饰对象的引用
abstract class Decorator implements Component {
  protected component: Component;

  constructor(component: Component) {
    this.component = component;
  }

  public operation(): string {
    return this.component.operation();
  }
}

// 实现具体的装饰器
class ConcreteDecoratorA extends Decorator {
  public operation(): string {
    return `ConcreteDecoratorA(${super.operation()})`;
  }
}

// 实现具体的装饰器
class ConcreteDecoratorB extends Decorator {
  public operation(): string {
    return `ConcreteDecoratorB(${super.operation()})`;
  }
}

// 使用装饰器模式
const component: Component = new ConcreteComponent();
const decoratedComponentA: Component = new ConcreteDecoratorA(component);
const decoratedComponentB: Component = new ConcreteDecoratorB(decoratedComponentA);

console.log(decoratedComponentB.operation()); // 输出 "ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))"

装饰器模式的主要优点在于它可以动态地扩展一个对象的功能,而不需要通过继承来创建子类。这种模式可以很好地解决以下问题:

  • 需要给一个对象添加一些额外的行为或职责,但不想用子类来实现。
  • 需要动态地给一个对象添加一些行为或职责,而不会影响其他对象。
  • 需要在不影响其他对象的情况下,从对象中移除一些行为或职责。

观察者模式

观察者模式(Observer Pattern)是一种行为型设计模式,用于对象之间的一对多依赖关系。在该模式中,一个对象(称为“主题”或“可观察对象”)维护一组依赖于它的对象(称为“观察者”),并在状态发生改变时通知它们。观察者模式可以实现松耦合的对象之间的交互,从而提高代码的可维护性和可扩展性。

下面是使用 TypeScript 实现观察者模式的示例代码:

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

class Subject {
  private observers: Observer[] = [];

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

  public removeObserver(observer: Observer): void {
    const index = this.observers.indexOf(observer);
    if (index !== -1) {
      this.observers.splice(index, 1);
    }
  }

  public notifyObservers(data: any): void {
    this.observers.forEach((observer) => {
      observer.update(data);
    });
  }
}

class ConcreteObserver implements Observer {
  public update(data: any): void {
    console.log(`Received data: ${data}`);
  }
}

// Usage example
const subject = new Subject();
const observer1 = new ConcreteObserver();
const observer2 = new ConcreteObserver();

subject.addObserver(observer1);
subject.addObserver(observer2);

subject.notifyObservers('Hello, world!');

subject.removeObserver(observer2);

subject.notifyObservers('Goodbye, world!');

在这个例子中,Subject 类是可观察对象,它维护了一组观察者(Observer)。观察者通过实现 Observer 接口来定义它们的更新方法。ConcreteObserver 是一个具体的观察者实现,它在收到通知时打印接收到的数据。