Skip to content

建造者模式

建造者模式(Builder Pattern)是一种创建型设计模式,它允许逐步构建复杂对象。建造者模式特别适用于需要构造的对象必须支持多种表示形式的情况。通过使用建造者模式,可以避免构造函数参数列表过长的问题,并且使得代码更加清晰易读。

建造者模式的主要角色

  1. Product(产品角色):需要创建的复杂对象。
  2. Builder(抽象建造者):为创建 Product 对象的各个部件指定抽象接口。
  3. ConcreteBuilder(具体建造者):实现了 Builder 接口,负责构建和装配 Product 对象的各个部件。
  4. Director(指挥者):使用 Builder 接口来构建最终的 Product 对象。

在 JavaScript 中的实现

下面是一个简单的建造者模式的实现示例:

示例:构建一辆汽车

javascript
// Product(产品角色)
class Car {
  constructor() {
    this.parts = [];
  }

  add(part) {
    this.parts.push(part);
  }

  show() {
    console.log("Car Parts: " + this.parts.join(", "));
  }
}

// Builder(抽象建造者)
class CarBuilder {
  constructor() {
    this.car = new Car();
  }

  buildFrame() {}
  buildEngine() {}
  buildWheels() {}
  buildDoors() {}
  getResult() {
    return this.car;
  }
}

// ConcreteBuilder(具体建造者)
class SportsCarBuilder extends CarBuilder {
  buildFrame() {
    this.car.add("Sport Frame");
  }

  buildEngine() {
    this.car.add("V8 Engine");
  }

  buildWheels() {
    this.car.add("Sport Wheels");
  }

  buildDoors() {
    this.car.add("Sport Doors");
  }
}

class SUVCarBuilder extends CarBuilder {
  buildFrame() {
    this.car.add("SUV Frame");
  }

  buildEngine() {
    this.car.add("Eco Engine");
  }

  buildWheels() {
    this.car.add("Offroad Wheels");
  }

  buildDoors() {
    this.car.add("Extra Doors");
  }
}

// Director(指挥者)
class Director {
  constructor(builder) {
    this.builder = builder;
  }

  construct() {
    this.builder.buildFrame();
    this.builder.buildEngine();
    this.builder.buildWheels();
    this.builder.buildDoors();
  }
}

// 使用示例
const sportsCarBuilder = new SportsCarBuilder();
const director = new Director(sportsCarBuilder);

director.construct();
const sportsCar = sportsCarBuilder.getResult();
sportsCar.show(); // 输出: Car Parts: Sport Frame, V8 Engine, Sport Wheels, Sport Doors

const suvCarBuilder = new SUVCarBuilder();
const director2 = new Director(suvCarBuilder);

director2.construct();
const suvCar = suvCarBuilder.getResult();
suvCar.show(); // 输出: Car Parts: SUV Frame, Eco Engine, Offroad Wheels, Extra Doors

代码解释

  • Product(产品角色)Car 类代表了我们想要构建的复杂对象。它可以包含多个部分,这些部分通过 add 方法添加到 parts 列表中,并可以通过 show 方法展示所有已添加的部分。
  • Builder(抽象建造者)CarBuilder 类定义了构建一个 Car 对象所需的方法,但没有提供具体的实现。
  • ConcreteBuilder(具体建造者)SportsCarBuilderSUVCarBuilder 类分别提供了不同类型的汽车的具体构建方法。
  • Director(指挥者)Director 类用于控制构建过程,确保按照一定的顺序调用建造者的构建方法。

应用场景

建造者模式非常适合用于以下场景:

  • 需要构建复杂对象时,尤其是当这个对象的构建过程需要很多步骤,并且这些步骤可能会有不同的组合方式。
  • 当对象的创建算法应该独立于构成它的组件以及它们的装配方式时。
  • 当希望隔离复杂对象的创建与使用时。

通过使用建造者模式,可以使对象的创建过程更加灵活,同时也提高了代码的可读性和可维护性。

与工厂模式的区别

建造者模式(Builder Pattern)和工厂模式(Factory Pattern)都是创建型设计模式,它们的主要目标是帮助我们更方便地创建对象。尽管两者都致力于简化对象的创建过程,但它们的应用场景和实现方式有所不同。

建造者模式

建造者模式主要用于解决在需要构建复杂对象时的问题,它允许逐步构造一个复杂的对象,并且使得同样的构建过程可以创建不同的表示。建造者模式通常用于当一个对象需要很多参数来构造,其中有些参数可能是可选的情况下。

主要角色:

  1. Builder(抽象建造者):为创建产品各个部分声明接口。
  2. ConcreteBuilder(具体建造者):实现 Builder 接口,定义并明确其对应的产品表示,并提供获取产品的方法。
  3. Director(指挥者):负责使用 Builder 接口来构建产品。
  4. Product(产品):最终生成的对象,包含多个组件构成的复杂结构。

特点:

  • 适用于构造复杂对象的情况。
  • 允许对象的构建过程与表示分离。
  • 提供了一种灵活的方式去创建不同形式的产品。

工厂模式

工厂模式是一种创建型设计模式,它提供了创建对象的一种接口,而不需要指定具体的类。工厂模式根据提供的数据自动实例化相应的类,从而隐藏了对象创建的逻辑。

根据其实现方式,工厂模式又分为三种:

  1. 简单工厂模式(Simple Factory):不属于 GoF 的 23 种设计模式之一,但它是最基础的形式,通过一个静态方法来决定创建哪个产品类的对象。
  2. 工厂方法模式(Factory Method):定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。也就是说,工厂方法将实际创建的工作推迟到子类中完成。
  3. 抽象工厂模式(Abstract Factory):提供一个接口,用于创建相关或依赖对象的家族,而无需明确指定具体类。

特点:

  • 工厂模式主要关注于对象的创建,而不关心对象的具体构建细节。
  • 简单工厂适合用于创建少量类型的产品;工厂方法适合用于扩展性高的场景;抽象工厂适合用于创建一系列相关的对象。

比较

  • 目的:建造者模式专注于如何一步一步地创建一个复杂的对象,而工厂模式则专注于如何创建一个对象(无论是简单的还是复杂的),并且不关心对象的内部组成。
  • 适用场景:当你需要创建一个复杂的对象,且这个对象的构造过程可以被分割成多个步骤时,应该选择建造者模式。而当你只需要创建一个对象,并且希望隐藏创建逻辑时,应该选择工厂模式。
  • 灵活性:建造者模式提供了更大的灵活性,因为它允许你在不同的时间点调用不同的方法来设置产品的属性,最后才调用一个方法来获取最终的产品。而工厂模式则通常是立即返回一个完整配置好的对象。

在 JavaScript 中的实现示例

建造者模式的例子:

javascript
// Product(产品)
class Product {
  constructor() {
    this.parts = [];
  }

  add(part) {
    this.parts.push(part);
  }

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

// Builder(抽象建造者)
class Builder {
  buildPartA() {}
  buildPartB() {}
  getResult() {}
}

// ConcreteBuilder(具体建造者)
class ConcreteBuilder extends Builder {
  constructor() {
    super();
    this.product = new Product();
  }

  buildPartA() {
    this.product.add("PartA");
  }

  buildPartB() {
    this.product.add("PartB");
  }

  getResult() {
    return this.product;
  }
}

// Director(指挥者)
class Director {
  constructor(builder) {
    this.builder = builder;
  }

  construct() {
    this.builder.buildPartA();
    this.builder.buildPartB();
  }
}

// 使用示例
const builder = new ConcreteBuilder();
const director = new Director(builder);

director.construct();
const product = builder.getResult();
product.show(); // 输出: Product parts: PartA, PartB

工厂方法模式的例子:

javascript
// Creator(抽象工厂)
class Creator {
  factoryMethod() {
    throw new Error("This method should be overridden");
  }

  someOperation() {
    const product = this.factoryMethod();
    console.log(
      `Creator: The same creator's code has just worked with ${product.operation()}`
    );
  }
}

// ConcreteCreator(具体工厂)
class ConcreteCreator1 extends Creator {
  factoryMethod() {
    return new ConcreteProduct1();
  }
}

class ConcreteCreator2 extends Creator {
  factoryMethod() {
    return new ConcreteProduct2();
  }
}

// Product(抽象产品)
class Product {
  operation() {
    throw new Error("This method should be overridden");
  }
}

// ConcreteProduct(具体产品)
class ConcreteProduct1 extends Product {
  operation() {
    return "{Result of ConcreteProduct1}";
  }
}

class ConcreteProduct2 extends Product {
  operation() {
    return "{Result of ConcreteProduct2}";
  }
}

// 使用示例
const creator1 = new ConcreteCreator1();
creator1.someOperation(); // 输出: Creator: The same creator's code has just worked with {Result of ConcreteProduct1}

const creator2 = new ConcreteCreator2();
creator2.someOperation(); // 输出: Creator: The same creator's code has just worked with {Result of ConcreteProduct2}

这两个模式各自有其独特的优势和应用场景,理解它们之间的区别有助于我们在软件开发过程中做出合适的设计选择。

Released under the MIT License.