It’s #FrontendFriday – Builder – Vereinfacht komplexe Prozesse beim Erzeugen von Objekten

25.03.2022

Hallo #FrontendFriday-Leser/in, in diesem Teil der Reihe Coding Patterns JavaScript schauen wir uns das Builder (zu deutsch Erbauer) Pattern an. Wie es der Name verrät, ist dies ein Pattern, um Objekte zu erzeugen (Erzeugungsmuster).

Was ist das Builder Pattern?

Das Prinzip ist es, zunächst alle nötigen Bestandteile zu sammeln. Sind alle Teile da, kann das Objekt gebaut werden. Hierzu direkt ein Beispiel, das eine Instanz der Klasse „Coffee“ auf konventionelle Art erzeugt und auch 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

Und hier die Definition der Klasse

// 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 diesem kleinen Beispiel können wir bereits folgende positiven Eigenschaften des Builders sehen:

  • Die Erzeugung der Objekte ist sprechender/lesbarer
  • Man könnte eine Validierung einbauen, um nur valide Kaffees erzeugen zu können
  • Hat man viele Attribute für ein Objekt, können diese per Builder einfacher genutzt werden (vor allem, wenn optionale Parameter im Spiel sind)
  • Komplexere Einstellungen können mit ‚Presets‘ hinterlegt werden. Würden wir beispielsweise das Objekt noch um einen Brühdruck erweitern, können die Presets um den Standardwert erweitert werden. So ist die Nutzung des „komplexen“ Objektes auch für nicht Profis nutzbar (Wie viel Brühdruck benötige ich für einen Espresso?).

Builder Pattern GoF

Das gezeigte Builder Pattern ist tatsächlich eine sehr starke Vereinfachung des Builder Patterns, das die Gang of Four (GoF) definiert hat. Oft wird aber dieses gemeint. Das hier gezeigte Beispiel auf das ‚original‘ übertragen könnte so sein (Getränkeautomat):

  • Wir können diverse Objekte mit den gleichen Schritten erstellen:
  • Schritt 1: Füge Pulver hinzu, Schritt 2: Füge Wasser hinzu, Schritt 3: Vermische Zutaten, Schritt 4: Fertiges Produkt
  • Ein „Direktor“ kennt diese Schritte, er muss nur wissen wer (Builder) sie durchführen soll
    • z.B. CoffeeBuilder, CacaoBuilder, TeaBuilder
  • Ein „Client“ sagt dem „Direktor“ welcher „Builder“ genutzt werden soll. Der Direktor ruft auf diesem die einzelnen Schritte auf.
  • Das Ergebnis ist dann entweder Kaffee, Kakao oder ein Tee

Fazit

Einsetzen sollte man das Pattern, wenn es einen Vorteil bewirkt: Hat man komplex zu erstellende Objekte, so ist dies eine sehr gute Möglichkeit die Erstellung zu vereinfachen. Schaut auch mal, ob eure IDE euch bei der Erstellung des Builders helfen kann.

 

Mehr zu Java Programmierung erfahren

Zurück zur Übersicht

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*Pflichtfelder

*