返回

洞悉js设计模式(二):灵活构建,挥洒创意

前端

创建型设计模式:对象创建的艺术

在软件工程中,创建型设计模式是一种处理对象创建的设计模式,它旨在根据实际情况使用合适的方式创建对象。创建型模式的主要思想是将对象创建的细节与对象的具体实现分离,以便创建对象时可以更灵活地应对需求变化。

四种创建型设计模式,各显其能

在JavaScript中,最常用的创建型设计模式包括:

  • 抽象工厂模式 :通过提供一个接口来创建相关的对象,而无需指定它们的具体类型,使系统独立于产品创建过程。

  • 建造者模式 :通过将复杂对象的构建与它的表示分离,使同一个构建过程可以创建不同的表示。

  • 原型模式 :通过创建一个类的实例,然后使用该实例作为模板来创建新的对象,使新对象与该原型具有相同的属性和方法。

  • 单例模式 :确保某一个类只有一个实例,并提供一个全局访问点来获取该实例。

1. 抽象工厂模式:统一管理,模块开发

抽象工厂模式旨在将产品族对象的创建与具体的实现代码分离,从而提高代码的可重用性和可维护性。它定义了一个抽象的工厂接口,该接口用于创建不同类型产品的对象。通过抽象工厂模式,我们可以轻松地切换不同类型的产品,而无需更改代码逻辑。

适用场景:

  • 同时创建多种相关或相互依赖的产品。
  • 需要在不暴露产品类的情况下控制产品创建过程。
  • 提高代码的可重用性,实现不同产品间的解耦。

代码示例:

// 定义抽象工厂接口
interface IAbstractFactory {
  createProductA(): ProductA;
  createProductB(): ProductB;
}

// 定义具体工厂类,实现IAbstractFactory接口
class ConcreteFactory1 implements IAbstractFactory {
  createProductA(): ProductA {
    return new ProductA1();
  }

  createProductB(): ProductB {
    return new ProductB1();
  }
}

class ConcreteFactory2 implements IAbstractFactory {
  createProductA(): ProductA {
    return new ProductA2();
  }

  createProductB(): ProductB {
    return new ProductB2();
  }
}

// 定义产品类
class ProductA {
  public operation(): string {
    return "ProductA";
  }
}

class ProductB {
  public operation(): string {
    return "ProductB";
  }
}

// 定义具体产品类
class ProductA1 extends ProductA {}
class ProductA2 extends ProductA {}

class ProductB1 extends ProductB {}
class ProductB2 extends ProductB {}

// 使用抽象工厂创建产品
let factory: IAbstractFactory = new ConcreteFactory1();
let productA: ProductA = factory.createProductA();
let productB: ProductB = factory.createProductB();

console.log(productA.operation()); // 输出:ProductA
console.log(productB.operation()); // 输出:ProductB

2. 建造者模式:复杂构建,分而治之

建造者模式将复杂对象的构建与它的表示分离,使得同一个构建过程可以创建不同的表示。它将对象的创建过程封装在建造者对象中,从而使客户端代码与对象的具体构建过程分离。

适用场景:

  • 需要创建复杂对象,且对象的各个组成部分可以独立创建。
  • 需要创建具有不同表示形式的对象。
  • 需要在不修改现有代码的情况下更改对象创建过程。

代码示例:

// 定义建造者接口
interface IBuilder {
  buildPartA(): void;
  buildPartB(): void;
  buildPartC(): void;
  getResult(): Product;
}

// 定义具体建造者类,实现IBuilder接口
class ConcreteBuilder1 implements IBuilder {
  private product: Product = new Product();

  buildPartA(): void {
    this.product.add("PartA1");
  }

  buildPartB(): void {
    this.product.add("PartB1");
  }

  buildPartC(): void {
    this.product.add("PartC1");
  }

  getResult(): Product {
    return this.product;
  }
}

class ConcreteBuilder2 implements IBuilder {
  private product: Product = new Product();

  buildPartA(): void {
    this.product.add("PartA2");
  }

  buildPartB(): void {
    this.product.add("PartB2");
  }

  buildPartC(): void {
    this.product.add("PartC2");
  }

  getResult(): Product {
    return this.product;
  }
}

// 定义产品类
class Product {
  private parts: string[] = [];

  public add(part: string): void {
    this.parts.push(part);
  }

  public listParts(): void {
    console.log("Product parts: " + this.parts.join(", "));
  }
}

// 定义指挥者类
class Director {
  private builder: IBuilder;

  constructor(builder: IBuilder) {
    this.builder = builder;
  }

  construct(): Product {
    this.builder.buildPartA();
    this.builder.buildPartB();
    this.builder.buildPartC();
    return this.builder.getResult();
  }
}

// 使用建造者和指挥者创建产品
let builder1: IBuilder = new ConcreteBuilder1();
let director: Director = new Director(builder1);
let product1: Product = director.construct();

let builder2: IBuilder = new ConcreteBuilder2();
let director2: Director = new Director(builder2);
let product2: Product = director2.construct();

product1.listParts(); // 输出:Product parts: PartA1, PartB1, PartC1
product2.listParts(); // 输出:Product parts: PartA2, PartB2, PartC2

3. 原型模式:克隆对象,节省开销

原型模式通过创建一个类的实例,然后使用该实例作为模板来创建新的对象,使新对象与该原型具有相同的属性和方法。这种模式可以避免重复创建对象,从而提高性能。

适用场景:

  • 需要创建大量相同或相似的对象。
  • 需要在运行时创建对象,而无需指定具体类。
  • 需要创建具有复杂初始化过程的对象。

代码示例:

// 定义原型类
class Prototype {
  public cloned(): Prototype {
    return new Prototype();
  }
}

// 定义具体原型类,实现Prototype接口
class ConcretePrototype extends Prototype {
  private field1: string;
  private field2: number;

  constructor(field1: string, field2: number) {
    this.field1 = field1;
    this.field2 = field2;
  }

  public cloned(): ConcretePrototype {
    return new ConcretePrototype(this.field1, this.field2);
  }

  public operation(): void {
    console.log(`Field1: ${this.field1}, Field2: ${this.field2}`);
  }
}

// 使用原型创建新的对象
let prototype: Prototype = new ConcretePrototype("field1 value", 123);
let clone1: Prototype = prototype.cloned();
let clone2: Prototype = prototype.cloned();

prototype.operation(); // 输出:Field1: field1 value, Field2: 123
clone1.operation(); // 输出:Field1: field1 value, Field2: 123
clone2.operation(); // 输出:Field1: field1 value, Field2: 123

4. 单例模式:独一无二,掌控全局

单例模式旨在确保某一个类只有一个实例,并提供一个全局访问点来获取该实例。这种模式可以确保全局范围内只有一个对象,从而控制该对象的创建和使用。

适用场景:

  • 需要创建一个全局可访问的对象,且该对象只允许有一个实例。
  • 需要控制对象创建的时机和方式。
  • 需要确保对象在整个应用程序中保持一致性。

代码示例:

// 定义单例类
class Singleton {
  private static instance: Singleton;

  private constructor() {}

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