Builder Pattern

Posted by Dustin Boston in .

The Builder Pattern is a creational design pattern that decouples the construction of complex objects from their representation, allowing for flexibility and reuse in object creation.


The Builder pattern decouples construction of an object from its underlying structure so that one builder can create multiple types of objects.

Source Code Listing

code.ts

class Part<T> {
  constructor(
    public type: string,
    public value: T,
  ) {}
}

class Director<T> {
  constructor(public builder: Builder<T>) {}

  construct(structure: Array<Part<T>>) {
    for (const part of structure) {
      switch (part.type) {
        case "a": {
          this.builder.buildPartA(part);
          break;
        }

        case "b": {
          this.builder.buildPartB(part);
          break;
        }

        default: {
          this.builder.buildPartA(part);
        }
      }
    }
  }
}

class Product<U> {
  constructor(public result: U[] = []) {}

  append(object: U) {
    this.result.push(object);
  }

  get() {
    return this.result;
  }
}

class Builder<T> {
  buildPartA(_part: Part<T>) {
    // Unimplemented
  }

  buildPartB(_part: Part<T>) {
    // Unimplemented
  }
}

class ConcreteBuilder1<T, U> extends Builder<T> {
  product = new Product<U>();

  buildPartA(part: Part<T>) {
    // Example building a part
    const value: U = String(part.value).toLowerCase() as unknown as U;
    this.product.append(value);
  }

  buildPartB(part: Part<T>) {
    // Example building a part
    const value: U = String(part.value).toUpperCase() as unknown as U;
    this.product.append(value);
  }

  getResult() {
    return this.product;
  }
}

// Other builders:
// class ConcreteBuilder2<T, U> extends Builder<T> {
// class ConcreteBuilder3<T, U> extends Builder<T> {

const client = {
  run() {
    const concreteBuilder = new ConcreteBuilder1<string, string>();
    const director = new Director(concreteBuilder);
    director.construct([new Part("a", "Hello"), new Part("b", "World")]);
    const result = concreteBuilder.getResult();
    console.log(result.get());
  },
};

client.run();