Builder Pattern

The Builder Pattern, also known as the Generator Pattern, separates the construction of a complex object from its representation, allowing the same construction process to create different representations. The Builder Pattern belongs to the category of object creation patterns.

Description

The Builder Pattern creates a complex object step by step, allowing users to build them by specifying only the type and content of the complex object, without needing to know the specific construction details internally.

Pattern Structure

  • Builder: Abstract Builder, the purpose of introducing an abstract builder is to delegate the specific construction process to be implemented by its subclasses. This makes it easier to extend. Generally, there are at least two abstract methods: one for building the product, and the other for returning the product.
  • ConcreteBuilder: Concrete Builder, implements all the unimplemented methods of the abstract class. Specifically, it usually involves two tasks: assembling the product and returning the assembled product.
  • Director: Director, responsible for calling the appropriate builder to assemble the product. The director usually does not have a direct dependency on the product class. The builder class directly interacts with the director. Generally, the director is used to encapsulate the parts of the program that are subject to change.
  • Product: Product role, generally a more complex object. The product class can be composed of an abstract class and its different implementations, or it can be composed of multiple abstract classes and their implementations.

Comparison

  • Compared to the Abstract Factory Pattern, the Builder Pattern returns a fully assembled complete product, while the Abstract Factory Pattern returns a series of related products that are part of different product families in different product hierarchy structures.
  • In the Abstract Factory Pattern, the client instantiates the factory class and then calls the factory method to obtain the required product object, while in the Builder Pattern, the client may not directly call the builder's related methods, but instead guides how to generate objects through the director class, including the object's assembly process and construction steps. It focuses on step-by-step construction of a complex object, returning a complete object.
  • If the Abstract Factory Pattern is seen as a car parts production factory that produces a product family, then the Builder Pattern is an automobile assembly factory, returning a complete car through the assembly of components.

Advantages

  • In the Builder Pattern, the client does not need to know the internal details of the product's composition, decoupling the product itself from the product's creation process, enabling the same creation process to create different product objects.
  • Each specific builder is relatively independent and unrelated to other specific builders, making it convenient to replace specific builders or add new specific builders. Users can obtain different product objects by using different specific builders.
  • It allows for finer control of the product's creation process, breaking down the creation steps of a complex product into different methods, making the creation process clearer and more convenient to control using the program.
  • Adding new specific builders does not require modifying the original class library. The director class is programmed against the abstract builder class, making system expansion convenient and in line with the open-closed principle.

Disadvantages

  • The products created by the Builder Pattern generally have many similarities, and their components are similar. If the differences between products are significant, the Builder Pattern may not be suitable, thus limiting its scope of use.
  • If the internal changes of the product are complex, it may lead to the need to define many specific builder classes to implement this change, making the system very large.

Implementation

class Product{ // Concrete Product
    constructor(){
        this.name = null;
        this.type = null;
    }
    setName(name){
        this.name = name;
    }
    setType(type){
        this.type = type;
    }
    showProduct(){
        console.log("name:", this.name);
        console.log("type:", this.type);
    }
}

class Builder{ // Abstract Builder
    setPart(name, type){
        throw new Error("Abstract method cannot be called");
    }
    getProduct(){
        throw new Error("Abstract method cannot be called");
    }
}

class ConcreteBuilder extends Builder{ // Concrete Builder
    constructor(){
        super();
        this.product = new Product();
    }
    build(name, type){
        this.product.setName(name);
        this.product.setType(type);
    }
    getProduct(){
        return this.product;
    }
}

class Director{ // Director
    constructor(){
        this.builder = new ConcreteBuilder();
    }
    getProductA(){
        this.builder.build("A", "TypeA");
        return this.builder.getProduct();
    }
getProductB(){
    this.builder.build("B", "TypeB");
    return this.builder.getProduct();
}
}

(function() {
var director = new Director();
var productA = director.getProductA();
productA.showProduct(); // name: A type: TypeA
var director = new Director();
var productB = director.getProductB();
productB.showProduct(); // name: B type: TypeB
})()

Daily Question

https://github.com/WindrunnerMax/EveryDay

References

https://www.runoob.com/design-pattern/builder-pattern.html https://wiki.jikexueyuan.com/project/java-design-pattern/builder-pattern.html https://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/builder.html