Skip to content

前端核心知识点 05

饿汉式单例(Eager Singleton)

ts
class EagerSingleton {
  // 在类定义时就创建实例
  private static instance: EagerSingleton = new EagerSingleton();

  // 私有构造函数,防止外部 new
  private constructor() {
    // 初始化逻辑
  }

  // 提供全局访问点
  public static getInstance(): EagerSingleton {
    return EagerSingleton.instance;
  }

  public someMethod(): void {
    console.log('This is an eager singleton method.');
  }
}

// 使用示例
const instance1 = EagerSingleton.getInstance();
const instance2 = EagerSingleton.getInstance();
console.log(instance1 === instance2); // true

懒汉式单例(Lazy Singleton)

ts
class LazySingleton {
  private static instance: LazySingleton | null = null;

  private constructor() {
    // 初始化逻辑
  }

  public static getInstance(): LazySingleton {
    if (LazySingleton.instance === null) {
      LazySingleton.instance = new LazySingleton();
    }
    return LazySingleton.instance;
  }

  public someMethod(): void {
    console.log('This is a lazy singleton method.');
  }
}

// 使用示例
const instance3 = LazySingleton.getInstance();
const instance4 = LazySingleton.getInstance();
console.log(instance3 === instance4); // true

简单工厂(Simple Factory)

text
// 1. 定义产品接口
interface Notification {
  send(message: string): void;
}

// 2. 具体产品类
class EmailNotification implements Notification {
  send(message: string): void {
    console.log(`[Email] Sending: ${message}`);
  }
}

class SMSNotification implements Notification {
  send(message: string): void {
    console.log(`[SMS] Sending: ${message}`);
  }
}

class InAppNotification implements Notification {
  send(message: string): void {
    console.log(`[In-App] Showing: ${message}`);
  }
}

// 3. 工厂类
class NotificationFactory {
  static create(type: 'email' | 'sms' | 'inapp'): Notification {
    switch (type) {
      case 'email':
        return new EmailNotification();
      case 'sms':
        return new SMSNotification();
      case 'inapp':
        return new InAppNotification();
      default:
        throw new Error(`Unknown notification type: ${type}`);
    }
  }
}

// 4. 使用
const emailNotif = NotificationFactory.create('email');
emailNotif.send('Hello via email!');

const smsNotif = NotificationFactory.create('sms');
smsNotif.send('Hello via SMS!');

工厂方法模式(Factory Method)

ts
// 抽象创建者
abstract class NotificationCreator {
  // 工厂方法(子类实现)
  abstract createNotification(): Notification;

  // 通用逻辑
  send(message: string): void {
    const notif = this.createNotification();
    notif.send(message);
  }
}

// 具体创建者
class EmailCreator extends NotificationCreator {
  createNotification(): Notification {
    return new EmailNotification();
  }
}

class SMSCreator extends NotificationCreator {
  createNotification(): Notification {
    return new SMSNotification();
  }
}

// 使用
const emailCreator = new EmailCreator();
emailCreator.send('Factory Method Email!');

const smsCreator = new SMSCreator();
smsCreator.send('Factory Method SMS!');

泛型工厂

ts
type NotificationType = 'email' | 'sms' | 'inapp';

// 映射类型:根据 key 返回具体类
interface NotificationMap {
  email: EmailNotification;
  sms: SMSNotification;
  inapp: InAppNotification;
}

class GenericNotificationFactory {
  static create<T extends NotificationType>(type: T): NotificationMap[T] {
    switch (type) {
      case 'email':
        return new EmailNotification() as NotificationMap[T];
      case 'sms':
        return new SMSNotification() as NotificationMap[T];
      case 'inapp':
        return new InAppNotification() as NotificationMap[T];
      default:
        throw new Error('Invalid type');
    }
  }
}

// 使用:类型精准推导!
const email = GenericNotificationFactory.create('email');
// email 类型是 EmailNotification,不是 Notification
email.send('Typed email!'); // ✅ 有完整类型提示

构建者模式

ts
// 1. 最终要创建的对象
type Car = {
  brand?: string;
  color?: string;
};

// 2. 构建者类(核心!)
class CarBuilder {
  private car: Car = {}; // 初始是个空车

  setBrand(brand: string): this {
    this.car.brand = brand;
    return this; // 返回自己,支持链式调用
  }

  setColor(color: string): this {
    this.car.color = color;
    return this;
  }

  build(): Car {
    return this.car; // 返回最终产品
  }
}

// 3. 怎么用?
const myCar = new CarBuilder()
  .setBrand('Tesla')
  .setColor('Red')
  .build();

console.log(myCar); // { brand: 'Tesla', color: 'Red' }

原型模式

text
// 1. 定义一个可克隆的接口(可选,用于规范)
interface Clonable<T> {
  clone(): T;
}

// 2. 一个具体的“原型”类
class User implements Clonable<User> {
  constructor(
    public name: string,
    public role: string = 'user',
    public settings: { theme: string; lang: string } = { theme: 'light', lang: 'en' }
  ) {}

  clone(): User {
    // 关键:返回一个新对象,属性值相同(深拷贝 or 浅拷贝看需求)
    return new User(this.name, this.role, { ...this.settings });
  }
}

// 3. 使用:先有一个“原型”,然后复制它
const adminPrototype = new User('Admin', 'admin', { theme: 'dark', lang: 'zh' });

// 克隆出多个相似用户
const user1 = adminPrototype.clone();
user1.name = 'Alice';

const user2 = adminPrototype.clone();
user2.name = 'Bob';
user2.settings.lang = 'ja';

console.log(adminPrototype); // 原型不变
console.log(user1);          // { name: 'Alice', role: 'admin', settings: { theme: 'dark', lang: 'zh' } }
console.log(user2);          // { name: 'Bob', role: 'admin', settings: { theme: 'dark', lang: 'ja' } }

适配器模式

ts
// 1. 【已有】老的日志类(不能改)
interface IPrinter {
  print(text:string) : void
}

class LegacyPrinter {
  printOldFormat(content: string):void {
    console.log(`[Legacy] ${content}`)
  }
}

class PrinterAdapter implements IPrinter  {
  private legacyPrinter: LegacyPrinter

  constructor(legacyPrinter:LegacyPrinter) {
    this.legacyPrinter = legacyPrinter
  }

  print(text: string) :void {
    this.legacyPrinter.printOldFormat(text)
  }
}

const legacy = new LegacyPrinter()

const adapter :IPrinter = new PrinterAdapter(legacy)

adapter.print('hello ,adapter pattern')

装饰器模式

ts
// 1. 组件接口(Component)
interface Beverage {
  cost(): number;
  description(): string;
}

// 2. 具体组件(Concrete Component)
class Coffee implements Beverage {
  cost(): number {
    return 5;
  }
  description(): string {
    return "Coffee";
  }
}

// 3. 装饰器基类(Decorator)
abstract class BeverageDecorator implements Beverage {
  constructor(protected beverage: Beverage) {}

  abstract cost(): number;
  abstract description(): string;
}

// 4. 具体装饰器(Concrete Decorator)
class MilkDecorator extends BeverageDecorator {
  cost(): number {
    return this.beverage.cost() + 2; // 加牛奶 +2 元
  }
  description(): string {
    return `${this.beverage.description()}, with Milk`;
  }
}

class SugarDecorator extends BeverageDecorator {
  cost(): number {
    return this.beverage.cost() + 1; // 加糖 +1 元
  }
  description(): string {
    return `${this.beverage.description()}, with Sugar`;
  }
}

// 使用示例
const coffee = new Coffee();
console.log(coffee.description(), '— ¥', coffee.cost());
// 输出: Coffee — ¥ 5

const coffeeWithMilk = new MilkDecorator(coffee);
console.log(coffeeWithMilk.description(), '— ¥', coffeeWithMilk.cost());
// 输出: Coffee, with Milk — ¥ 7

const coffeeWithMilkAndSugar = new SugarDecorator(coffeeWithMilk);
console.log(coffeeWithMilkAndSugar.description(), '— ¥', coffeeWithMilkAndSugar.cost());
// 输出: Coffee, with Milk, with Sugar — ¥ 8

代理模式

ts
// 1. 定义共同接口
interface IImage {
  display(): void;
}

// 2. 真实对象(Real Subject)
class RealImage implements IImage {
  constructor(private filename: string) {
    this.loadFromDisk();
  }

  private loadFromDisk(): void {
    console.log(`Loading image: ${this.filename}`);
  }

  display(): void {
    console.log(`Displaying image: ${this.filename}`);
  }
}

// 3. 代理对象(Proxy)
class ImageProxy implements IImage {
  private realImage: RealImage | null = null;

  constructor(
    private filename: string,
    private isLoggedIn: boolean = false
  ) {}

  display(): void {
    if (!this.isLoggedIn) {
      console.log("Access denied: Please log in.");
      return;
    }

    if (!this.realImage) {
      this.realImage = new RealImage(this.filename); // 懒加载
    }
    this.realImage.display();
  }
}

// 使用示例
const proxy = new ImageProxy("photo.jpg", false);
proxy.display(); 
// 输出: Access denied: Please log in.

const proxy2 = new ImageProxy("photo.jpg", true);
proxy2.display(); 
// 输出: 
// Loading image: photo.jpg
// Displaying image: photo.jpg

外观模式

ts
// 子系统类
class CPU {
  start() {
    console.log("CPU started");
  }
}

class Memory {
  load() {
    console.log("Memory loaded");
  }
}

class HardDrive {
  read() {
    console.log("HardDrive data read");
  }
}

// 外观类:封装子系统操作
class ComputerFacade {
  private cpu = new CPU();
  private memory = new Memory();
  private hardDrive = new HardDrive();

  turnOn() {
    this.hardDrive.read();
    this.memory.load();
    this.cpu.start();
    console.log("Computer is ready!");
  }
}

// 客户端使用
const pc = new ComputerFacade();
pc.turnOn();
// 输出:
// HardDrive data read
// Memory loaded
// CPU started
// Computer is ready!

桥接模式

ts
// 实现部分
interface Implementor {
  operation(): void;
}

class ConcreteImplementorA implements Implementor {
  operation() { console.log("A"); }
}

class ConcreteImplementorB implements Implementor {
  operation() { console.log("B"); }
}

// 抽象部分
class Abstraction {
  constructor(private impl: Implementor) {}

  doSomething() {
    this.impl.operation();
  }
}

// 使用
const a = new Abstraction(new ConcreteImplementorA());
const b = new Abstraction(new ConcreteImplementorB());

a.doSomething(); // 输出: A
b.doSomething(); // 输出: B

组合模式

ts
// 组件接口:定义统一操作
interface Component {
  operation(): void;
}

// 叶子节点:不能再包含子节点
class Leaf implements Component {
  constructor(private name: string) {}

  operation(): void {
    console.log(`Leaf: ${this.name}`);
  }
}

// 容器节点:可包含子组件
class Composite implements Component {
  private children: Component[] = [];

  add(component: Component): void {
    this.children.push(component);
  }

  operation(): void {
    for (const child of this.children) {
      child.operation();
    }
  }
}

// 使用示例
const root = new Composite();
root.add(new Leaf("Leaf1"));
root.add(new Leaf("Leaf2"));

const subComposite = new Composite();
subComposite.add(new Leaf("Leaf3"));
root.add(subComposite);

root.operation();

享元模式

ts
// 享元接口
interface Flyweight {
  operation(extrinsicState: string): void;
}

// 具体享元
class ConcreteFlyweight implements Flyweight {
  constructor(private intrinsicState: string) {}

  operation(extrinsicState: string): void {
    console.log(`Intrinsic: ${this.intrinsicState}, Extrinsic: ${extrinsicState}`);
  }
}

// 享元工厂(确保共享)
class FlyweightFactory {
  private flyweights: { [key: string]: Flyweight } = {};

  getFlyweight(key: string): Flyweight {
    if (!this.flyweights[key]) {
      this.flyweights[key] = new ConcreteFlyweight(key);
    }
    return this.flyweights[key];
  }
}

// 使用示例
const factory = new FlyweightFactory();

const f1 = factory.getFlyweight("A");
const f2 = factory.getFlyweight("A");
const f3 = factory.getFlyweight("B");

console.log(f1 === f2); // true —— 共享同一个对象
console.log(f1 === f3); // false

f1.operation("context1"); // Intrinsic: A, Extrinsic: context1
f2.operation("context2"); // Intrinsic: A, Extrinsic: context2

观察者模式

最基础实现(无泛型)

ts
// 观察者接口
interface Observer {
  update(): void;
}

// 被观察者(主题)
class Subject {
  private observers: Observer[] = [];

  addObserver(obs: Observer) {
    this.observers.push(obs);
  }

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

// 具体观察者
class ConcreteObserver implements Observer {
  constructor(private name: string) {}

  update() {
    console.log(`${this.name} received update!`);
  }
}

// 使用
const subject = new Subject();
subject.addObserver(new ConcreteObserver("A"));
subject.addObserver(new ConcreteObserver("B"));
subject.notify();

支持传递数据(带 payload)

ts
type EventData = any; // 或定义具体类型

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

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

  addObserver(obs: Observer) {
    this.observers.push(obs);
  }

  notify(data: EventData) {
    this.observers.forEach(obs => obs.update(data));
  }
}

class Logger implements Observer {
  update(data: EventData) {
    console.log("Log:", data);
  }
}

// 使用
const subject = new Subject();
subject.addObserver(new Logger());
subject.notify("User logged in");

泛型 + 简洁写法(推荐日常使用)

ts
type Observer<T> = (data: T) => void;

class Subject<T> {
  private observers: Observer<T>[] = [];

  subscribe(obs: Observer<T>) {
    this.observers.push(obs);
  }

  notify(data: T) {
    this.observers.forEach(obs => obs(data));
  }
}

// 使用
const clickSubject = new Subject<string>();
clickSubject.subscribe(msg => console.log("Button:", msg));
clickSubject.subscribe(msg => console.log("Analytics:", msg));

clickSubject.notify("clicked!");