Das Builder Pattern gehört zu den Design Patterns – vielfach bewährten Vorlagen zur Lösung von Pro­gram­mier­auf­ga­ben in der ob­jekt­ori­en­tier­ten Pro­gram­mie­rung. Sie er­leich­tern den Ent­wick­lern die Pro­gram­mie­rung, da nicht jeder wie­der­holt auf­tre­ten­de Schritt erneut als Pro­gramm­rou­ti­ne erdacht werden muss, sondern auf eine bereits eta­blier­te Lösung zu­rück­ge­grif­fen werden kann. Diese Software-Elemente gehen auf das 1994 er­schie­ne­ne Buch „Ent­wurfs­mus­ter. Elemente wie­der­ver­wend­ba­rer ob­jekt­ori­en­tier­ter Software“ von vier US-Software-Ent­wick­lern zurück – bekannt als die Vie­rer­ban­de (engl. „Gang of Four“, abgekürzt GoF). Unser Ratgeber stellt Ihnen die we­sent­li­chen Aspekte des Erbauer-Ent­wurfs­mus­ters mit einem prak­ti­schen Beispiel vor.

Das Builder Pattern im Detail

Das Builder Pattern gehört zur Gruppe der Er­zeu­gungs­mus­ter aus den Design Patterns. Es ver­bes­sert sowohl die Si­cher­heit bei der Kon­struk­ti­on als auch die Les­bar­keit des Pro­gramm­codes. Das Ziel des Erbauer-Ent­wurfs­mus­ters ist, dass ein Objekt nicht mit den bekannten Kon­struk­to­ren erstellt wird, sondern mittels einer Hilfs­klas­se.

Zitat

„Separate the con­s­truc­tion of a complex object from its re­pre­sen­ta­ti­on so that the same con­s­truc­tion process can create different re­pre­sen­ta­ti­ons.“

Über­set­zung: „Trennen Sie die Kon­struk­ti­on eines komplexen Objekts von seiner Dar­stel­lung, so dass derselbe Kon­struk­ti­ons­pro­zess ver­schie­de­ne Dar­stel­lun­gen erzeugen kann.“ (Übers. von IONOS)

– Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (= „Gang of Four“)

Quelle: Design Patterns: Elements of Reusable Object-Oriented Software (Englisch) 1. Auflage, Her­aus­ge­ber: Addison-Wesley Pro­fes­sio­nal; 1. Auflage (10. November 1994)

Im Builder Design Pattern werden vier Akteure un­ter­schie­den:

  • Direktor: Dieser Akteur kon­stru­iert das komplexe Objekt, indem er die Schnitt­stel­le des Erbauers verwendet. Er kennt die An­for­de­run­gen an die Ar­beits­rei­hen­fol­ge des Erbauers. Beim Direktor wird die Kon­struk­ti­on eines Objekts vom Kunden („Auf­trag­ge­ber“) ent­kop­pelt.
  • Erbauer: Hält eine Schnitt­stel­le zur Erzeugung der Be­stand­tei­le eines komplexen Objekts (bzw. Produkts) bereit.
  • Konkreter Erbauer: Dieser Akteur erzeugt die Teile des komplexen Objekts und definiert (und verwaltet) die Re­prä­sen­ta­ti­on des Objekts und hält eine Schnitt­stel­le zur Ausgabe des Objekts vor.
  • Produkt: Das Ergebnis der „Tätigkeit“ des Builder Patterns, also das zu kon­stru­ie­ren­de komplexe Objekt.

Beim Direktor geschieht der ent­schei­den­de Vorgang des Erbauer-Musters, die Trennung der Her­stel­lung eines Objekts/Produkts vom Auf­trag­ge­ber.

Das Builder Pattern in UML-Dar­stel­lung

Für die grafische Dar­stel­lung von Pro­gram­mier­ab­läu­fen wird die ver­ein­heit­lich­te Mo­del­lie­rungs­spra­che, kurz UML (Unified Modeling Language), genutzt. Die Grafik zeigt, dass das Erbauer-Muster aus mehreren, mit­ein­an­der agie­ren­den Objekten besteht.

Plus und Minus des Erbauer-Musters

Vorteile des Erbauer-Ent­wurfs­mus­ters

Die Kon­struk­ti­on (das Erbauen) und die Re­prä­sen­ta­ti­on (die Ausgabe) werden von­ein­an­der isoliert ein­ge­bun­den. Die internen Re­prä­sen­ta­tio­nen der Erbauer sind vor dem Direktor „versteckt“. Neue Re­prä­sen­ta­tio­nen können leicht durch neue konkrete Er­bau­er­klas­sen eingefügt werden. Der Prozess der Kon­struk­ti­on wird vom Direktor als explizite Stelle gesteuert. Müssen dabei Än­de­run­gen vor­ge­nom­men werden, ist das ohne Rück­fra­gen beim Klienten möglich.

Nachteile des Builder Patterns

Es besteht eine enge Kopplung zwischen Produkt, konkretem Erbauer und den am Kon­struk­ti­ons­pro­zess be­tei­lig­ten Klassen, so dass Än­de­run­gen am grund­sätz­li­chen Prozess schwierig sein können. Das Erbauen (Kon­struk­ti­on) der Objekte erfordert oft Wissen über deren spezielle Ver­wen­dung und ihre Umgebung. Die Nutzung von bekannten Patterns, so auch des Erbauer-Ent­wurfs­mus­ters, können Pro­gram­mie­rer dazu verleiten, ein­fa­che­re und viel­leicht ele­gan­te­re Lösungen zu übersehen. Letztlich gilt das Erbauer-Muster unter Pro­gram­mie­rern als eines der weniger wichtigen Ent­wurfs­mus­ter.

Wo kommt das Builder Pattern zum Einsatz?

Eine Mög­lich­keit, das Erbauer-Ent­wurfs­mus­ter zu ver­deut­li­chen, ist ein ver­ein­facht dar­ge­stell­tes Re­stau­rant, in dem ein Gast ein Menü bestellt. Die ver­schie­de­nen Akteure des Re­stau­rants agieren nach dem Eingang der Be­stel­lung, um diese aus­zu­füh­ren. Der gesamte Vorgang bis zum Erhalt des be­stell­ten Menüs spielt sich „hinter den Kulissen“ ab. Der Gast sieht z. B. nicht, was in der Küche geschieht, um seine Be­stel­lung aus­zu­füh­ren – er bekommt das Ergebnis an seinem Tisch serviert (in Pro­gram­mier­spra­che: aus­ge­druckt = print).

Die folgenden Code-Ab­schnit­te stellen alle Akteure des Builder Patterns separat vor.

Das Objekt, das komplette Menü, ist an­fäng­lich leer; mit der Be­stel­lung wird es mit Inhalten gefüllt:

public class Menue {
	private String starter = "Keine Vorspeise";
	private String maincourse = "Kein Hauptgericht";
	private String dessert = "Keine Nachspeise";
	private String drink = "Kein Getränk";
	public void setVorspeise(String starter) {
		this.starter = starter;
	}
	public void setHauptgericht (String maincourse) {
		this.maincourse = maincourse;
	}
	public void setNachspeise(String dessert) {
		this.dessert = dessert;
	}
	public void setGetraenk(String drink) {
		this.drink = drink;
	}
	public void print() {
		System.out.println(
			"Das Menue ist fertig! " + "\n" +
			" – Vorspeise: " + starter +
			" – Hauptgericht: " + maincourse +
			" – Nachspeise: " + dessert +
			" – Getränk: " + drink);
	}
}

Der Direktor stellt die „Umgebung“ bereit, dass überhaupt ein Menü für den Gast her­ge­stellt – erbaut – werden kann. Diese Umgebung ist für jeden Gast zu­gäng­lich. Der Gast kom­mu­ni­ziert aus­schließ­lich mit dem Direktor, so dass ihm die ei­gent­li­che Erzeugung verborgen bleibt:

public class MattsRestaurant {
	private MenuBuilder menuBuilder;
	public void setBuilder(MenuBuilder menuBuilder) {
		this.menuBuilder = menuBuilder;
	}
	public Menu buildMenu(){
		menuBuilder.buildStarter();
		menuBuilder.buildMainCourse();
		menuBuilder.buildDessert();
		menuBuilder.buildDrink();
		return menuBuilder.build();
	}
}

Dann tritt der Erbauer in Aktion. Im gewählten Beispiel wäre das ein Kü­chen­chef:

public abstract class MenuBuilder {
	Menu menu = new Menu();
	abstract void buildStarter();
	abstract void buildMainCourse();
	abstract void buildDessert();
	abstract void buildDrink();
	Menu build()
{
		return menu;
	}
}

Der konkrete Erbauer, hier also der Koch, erbaut (kon­stru­iert/kocht) die einzelnen Be­stand­tei­le des be­stell­ten Menüs. Dazu über­schreibt (override) er die vor­lie­gen­den „abs­trak­ten“ Menü-Punkte:

public class MenuOfTheDayBuilder extends MenuBuilder {
	@Override
	public void buildStarter() {
		burger.setStarter("Kürbis-Suppe");
	}
	@Override
	public void buildMainCourse() {
		burger.setMainCourse("Gegrilltes Rindfleisch mit Pommes Frites");
	}
	@Override
	public void buildDessert() {
		burger.setDessert("Vanille-Eis");
	}
	@Override
	public void buildDrink() {
		burger.setDrink("Hauswein Rot");
	}
}

Schließ­lich werden die einzelnen Punkte zu­sam­men­ge­fasst aus­ge­führt und an den Gast aus­ge­lie­fert, in der Pro­gram­mier­spra­che also „aus­ge­druckt“:

public class Main {
	public static void main(String[] args) {
		MattsRestaurant mattsRestaurant = new MattsRestaurant();
		menuRestaurant.setBuilder(new MenuOfTheDayBuilderBuilder());
		buildMenu(menuRestaurant);
		menuRestaurant.setBuilder(new SpecialMenuBuilder());
		buildMenu(menuRestaurant);
	}
	private static void buildMenu(MattsRestaurant mattsRestaurant) {
		MenuOfTheDay menu = mattsRestaurant.buildMenu();
		menu.print();
	}
}
Hinweis

Das gewählte Beispiel beruht auf den Codes von Daniel Høyer Jacobsen, der auf seiner Webseite Design Patterns in Java mehrere Ent­wurfs­mus­ter il­lus­triert vorstellt.

Zum Hauptmenü