It's #FrontendFriday

It's #FrontendFriday - Builder - Simplifies complex processes when creating objects

,

Hello #FrontendFriday-reader, in this part of the series Coding Patterns JavaScript let's take a look at the Builder pattern. As the name suggests, this is a pattern for creating objects (creation pattern).

What is the Builder Pattern?

The principle is to collect all the necessary components first. Once all the parts are there, the object can be built. Here is an example that creates an instance of the "Coffee" class in the conventional way and also via Builder:

// Erzeugung einer Instanz auf 'normale' Art
let manualyCreatedCoffee = new Coffee(200, 20, 1);
manualyCreatedCoffee.print(); // Water: 200 Milk: 20 Sugar: 1

// Erzeugung einer Instanz auf "Builder" Art
let coffee = new Coffee.CoffeeBuilder()
  .withSugar(2)
  .withWater(200)
  .withMilk(0)
  .build();
coffee.print(); // Water: 200 Milk: 0 Sugar: 2

let espresso = new Coffee.CoffeeBuilder()
  .espresso()
  .withSugar(1)
  .build();
espresso.print(); // Water: 50 Milk: 0 Sugar: 1

And here is the definition of the class

// Klasse die Attribute für einen Kaffee enthält
class Coffee {
  #water
  #sugar
  #milk

  constructor(water, milk, sugar) {
    this.#water = water;
    this.#milk = milk;
    this.#sugar = sugar;
  }

  print() {
    console.log("Water:", this.#water, "Milk:", this.#milk, "Sugar:", this.#sugar);
  }

  // Hier wird ein Builder definiert (muss nicht Teil der Klasse sein)
  static CoffeeBuilder = class {
    #water = 0
    #milk = 0
    #sugar = 0

    // Methoden um einzelne Attribute zu setzen
    withWater(waterInMl) {
      this.#water = waterInMl;
      return this; // Gibt die Builder Instanz zurück. So können die Einstellungen aneinander gekettet werden.
    }

    withMilk(milkInMl) {
      this.#milk = milkInMl;
      return this;
    }

    withSugar(cubes) {
      this.#sugar = cubes;
      return this;
    }

    // Methoden, die mehrere Attribute setzen - wie presets für einen Kaffee
    normal() {
      this.#water = 200;
      this.#milk = 0;
      this.#sugar = 0;
      return this;
    }

    espresso() {
      this.#water = 50;
      this.#milk = 0;
      this.#sugar = 0;
      return this;
    }

    // Erst bei build wird der eigentliche Kaffee erzeugt
    build() {
      // Hier könnte man auch validieren, ob alle Attribute valide sind
      return new Coffee(this.#water, this.#milk, this.#sugar);
    }
  }
}

In this small example, we can already see the following positive features of the builder:

  • The creation of the objects is more speaking/readable
  • A validation could be built in so that only valid coffees can be created
  • If you have many attributes for an object, they can be used more easily via the builder (especially if optional parameters are involved)
  • More complex settings can be stored with 'Presets'. For example, if we were to add a brewing pressure to the object, the presets can be extended by the default value. This means that the 'complex' object can also be used by non-professionals (How much brewing pressure do I need for an espresso?).

Builder Pattern GoF

The builder pattern shown is actually a very strong simplification of the builder pattern defined by the Gang of Four (GoF). However, this is often what is meant. The example shown here could be transferred to the 'original' (vending machine):

  • We can create various objects with the same steps:
  • Step 1: Add powder, Step 2: Add water, Step 3: Mix ingredients, Step 4: Finished product
  • A "director" knows these steps, he just needs to know who (builder) should carry them out
    • e.g. CoffeeBuilder, CacaoBuilder, TeaBuilder
  • A "Client" tells the "Director" which "Builder" is to be used. The director calls up the individual steps on this.
  • The result is either coffee, cocoa or tea

Conclusion

You should use the pattern if it provides an advantage: If you have complex objects to create, this is a very good way to simplify the creation. Also check whether your IDE can help you create the builder.

 

Learn more about Java programming

Nico Mutter

About ME

Nico Mutter studied computer science (M.Sc.) and has been working as a software developer at doubleSlash in Friedrichshafen since 2016. His focus is on the architecture and development of IoT projects. He also has extensive expertise in 3D rendering and mixed reality.

All contributions from Nico Mutter

Learn more

Further information on our website and in our newsletter

Arrow up