Grundlagen der Programmierung: Entwurfsmuster

Erbauer: Lösung und Umsetzung

Testen Sie unsere 1927 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
Das "Erbauer"-Muster bietet eine Möglichkeit, Objekte in einem mehrschrittigen Prozess erzeugen zu können, ohne tatsächlich etwas über den eigentlichen Konstruktionsprozess wissen zu müssen. Wie das funktioniert, erfahren Sie in diesem Video.
07:36

Transkript

Für die Erzeugung von Objekten mit einer Reihe von Attributen, von denen viele optional sind und obendrein noch Abhängigkeiten zwischen einzelnen Attributen bestehen, sind weder eine möglichst große Anzahl von Konstruktoren noch das Einführen von Set-Methoden für alle Attribute wirklich praktikabel. Schauen wir uns an, welchen Lösungsvorschlag das Entwurfsmuster Erbauer bereithält. Dazu machen wir etwas Platz in unserer Klasse Schrank, denn dort kommt jetzt eine zweite Klasse hinein, der Erbauer. Dieser Erbauer wird zuständig sein für die Erzeugung von Schrankobjekten. Dazu bietet dieser Erbauer erst mal einen Konstruktor an und alle Attribute, die auf jeden Fall für die Erzeugung eines Schranks benötigt werden, an diesen Erbauer übergeben. In diesem Fall ist das nur die Anzahl der Türen, die der Schrank später haben soll. Als nächstes bietet der Erbauer eine Anzahl von Methoden an, mit denen das Schrankobjekt konfiguriert werden kann. Auf diese Weise lässt sich zum Beispiel die Farbe festlegen oder dass der Schrank eine Kleiderstange haben soll. Bis hier hin wird das Schrankobjekt lediglich konfiguriert. Um es tatsächlich erzeugen und an den Client ausliefern zu können, brauchen wir noch eine letzte Methode im Erbauer, die Methode konstruiere. Ein Client, der nun einen Schrank haben möchte, holt sich zuerst einen Erbauer und übergibt die Pflichtattribute als Parameter. Danach kann der Client den Schrank konfigurieren, so wie er ihn gerne haben möchte, indem er die passenden Methoden aufruft. Er muss dabei nur die Methoden aufrufen, die aus seiner Sicht tatsächlich von Bedeutung sind. Sind alle Informationen zusammengestellt, dann teilt der Client dem Erbauer mit, dass der Schrank nach diesen Vorgaben nun konstruiert werden kann. Der Erbauer macht nun genau das und liefert den fertigen Schrank an den Client aus. Schauen wir uns die praktische Umsetzung in Java Quelltext an. Dieses Projekt enthält zwei Aufzählungstypen, einen für die Farben, die ein Schrank haben kann und einen für die verschiedenen Arten von Oberflächen, also unbehandelt oder gewachst oder lackiert und natürlich haben wir hier den Schrank mit dem integrierten Erbauer. Diese Schrankklasse enthält in diesen Konstanten die Minimal- und Maximalwerte für die Anzahl der Türen und Einlegeböden und danach kommen alle Attribute, die ein Schrank so hat. Schließlich gibt es noch einen einzelnen Konstruktor, der den Pflichtparameter übernimmt, nämlich die Anzahl der Türen. Dieser Konstruktor ist private, kann also nur innerhalb dieser Klasse verwendet werden. Auf diese Weise wird verhindert, dass ein Client sich selbst einen Schrank erzeugen könnte, der dann möglicherweise fehlerhaft oder unvollständig ist. Nun schauen wir uns die Klasse Erbauer an, die sich innerhalb der Klasse Schrank befindet. Der Erbauer soll in einem mehrschrittigen Prozess ein Schrankobjekt erzeugen. In diesem Attribut merkt sich der Erbauer, wo sich der noch unfertige Schrank befindet. Der Erbauer hat einen öffentlichen Konstruktor, der den Pflichtparameter anzahlTueren übernimmt. Dieser Parameter wird dann überprüft und falls der Test fehlschlägt, wird eine IllegalArgumentException geworfen. War hingegen alles in Ordnung, dann wird hier sozusagen der minimale Schrank erzeugt. Dazu wird der private Konstruktor von Schrank aufgerufen und da sich der Erbauer innerhalb der Klasse Schrank befindet, hat er auch Zugriff auf diesen Konstruktor. Danach werden alle optionalen Attribute mit Standardwerten belegt. Auch hier kommt uns wieder zugute, dass der Erbauer sich innerhalb der Klasse Schrank befindet. Die Attribute sind zwar alle private. Ich zeige das nochmal hier. Aber der Erbauer hat natürlich Zugriff darauf. Nun folgen die Methoden, mit denen der Client später den Schrank konfigurieren kann. Jede dieser Methoden hat einen aussagekräftigen Namen und liefert eine Referenz auf den Erbauer selbst zurück, dadurch lassen sich später die einzelnen Methodenaufrufe direkt hintereinander hängen. Unterliegt ein Attribut bestimmten Einschränkungen, dann wird die Überprüfung direkt in der jeweiligen Methode vorgenommen. Hier zum Beispiel die Anzahl der Einlegeböden. Passt alles, wird diese Anzahl übernommen, wenn nicht, gibt es auch hier wieder eine entsprechend Exception. Durch Aufruf dieser Methoden kann der Client also den Schrank, den er später gerne haben möchte, Schritt für Schritt konfigurieren. Wenn er damit fertig ist, ruft er am Ende die Methode konstruiere auf. Hier können nun noch zusätzliche Validierungen vorgenommen werden. Zum Beispiel wenn Abhängigkeiten zwischen mehreren Attributen bestehen. Hier zum Beispiel gibt es einen Zusammenhang zwischen der Art der Oberfläche des Schranks und der Farbe. Wenn wir den Schrank lackiert oder gewachst haben möchten, dann können wir uns dafür eine passende Farbe aussuchen. Entscheiden wir uns aber für eine unbehandelte Oberfläche, dann ist die Farbe von vornherein hellbraun. Sollte der Client etwas anderes konfiguriert haben, dann bekommt er an dieser Stelle eine entsprechende Exception. Wenn alles in Ordnung war, dann liefert diese Methode an den Client schließlich den fertig konfigurierten Schrank aus. Wie arbeitet nun der Client mit diesem Erbauer? Schauen wir uns dazu diese Main Methode an, in der ein paar Schränke gebaut werden. Im ersten Beispiel möchte der Kunde einfach nur einen Schrank mit zwei Türen. Alles andere soll so sein, wie es standardmäßig ist. Er erzeugt sich also ein Erbauerobjekt, übergibt die Anzahl der Türen und da nichts weiter zu konfigurieren ist, ruft er als nächstes direkt konstruiere auf. Konstruiere liefert den Schrank zurück und der Client kann den Schrank entgegennehmen und benutzen. Da alle Attribute des Schranks private sind und keine Setter existieren, kann der Client auch im Nachhinein keine Veränderungen an diesem Schrank mehr vornehmen und dadurch eventuell einen inkonsistenten internen Zustand im Schrank erzeugen. Möchte der Client alles individuell konfigurieren, dann sieht das so aus. Hier legen wir zum Beispiel fest, wir hätten gerne 5 Türen. Also holen wir uns einen Erbauer für einen Schrank mit 5 Türen. Durch die Aufrufe der entsprechenden Methoden legen wir hier jetzt fest, dass der Schrank lackiert sein soll und zwar cremefarben, das er Metallschienen für die Schubladen haben soll, 6 Einlegeböden und eine Kleiderstange. Schließlich wird zum Schluss wieder konstruiere aufgerufen, was den entsprechend Schrank fertigstellt und zurückliefert. Hier können Sie auch sehen, wie das mit dem Aneinanderhängen der Methodenaufrufe funktioniert und wie das insgesamt die Lesbarkeit des Quelltextes deutlich verbessert. Der Client ist beim Aufruf der einzelnen Methoden, um die Attribute zu setzen, nicht an eine bestimmte Reihenfolge gebunden und er kann auch tatsächlich nur die Methoden aufrufen, die für ihn von Bedeutung sind. Das heißt, wenn der Client zum Beispiel einfach nur einen Schrank mit 2 Türen haben will, der insgesamt dem Standard entspricht, nur eben mit Kleiderstange sein soll, dann sagt er dem Erbauer genau das. Er holt sich einen Erbauer für einen Schrank mit 2 Türen, sagt mit Kleiderstand und lässt den Schrank konstruieren. Das Gleiche nur mit Metallschiene heißt dann eben Erbauer Schrank mit 2 Türen mit Metallschienen. Mach was. Dadurch dass die Methoden alle unterschiedliche Namen haben, also hier mit Kleiderstange, hier mit Metallschienen, gibt es hier auch keine Kollisionen, wie das bei mehreren Konstruktoren zum Beispiel der Fall wäre. Der Vollständigkeit halber führen wir das Programm jetzt noch aus und wir sehen, es werden tatsächlich hier verschiedene Schränke gebaut. Es gibt keine Fehlermeldungen und die Schränke sehen auch tatsächlich alle so aus, wie sie bestellt wurden. Betrachten wir nun zusammenfassend die Vor- und Nachteile des Erbauers. Der Erbauer vereinfacht für den Client die Erstellung komplexer Objekte und der Clientcode wird besser lesbar. Der Erbauer bietet für die Konfiguration der einzelnen Attribute sprechende Methodennamen, die auf den ersten Blick erkennen lassen, was wir dort konfigurieren. Wenn wir hingegen einen Konstruktor haben mit Parametern wie 6, 5, true, false, 17, dann ist nicht unbedingt sofort erkennbar, was das bedeutet. Schließlich bietet der Erbauer die Möglichkeit, dass das Objekt vor der endgültigen Erstellung und Auslieferung noch einmal validiert werden kann, damit der Client keine unvollständigen oder inkonsistenten Objekte bekommt. Kommen wir zu den Nachteilen. Ein offensichtlicher Punkt ist, dass wir ein zusätzliches Objekt erzeugen müssen, nämlich den Erbauer selbst. Außerdem steigt die Komplexität unseres Codes durch diese Erbauerklasse. Das bedeutet, dass dieser Mehraufwand auch erst sinnvoll ist, wenn wir eine bestimmte Mindestanzahl von Parameter haben. Das sind tatsächlich so in der Regel mindestens 5 bis 6. Schließlich benötigt der Client natürlich ein bestimmtes Maß an Wissen über den Aufbau des zu erzeugenden Objekts, damit er die richtigen Methoden aufrufen kann. Damit kennen Sie nun das Entwurfsmuster Erbauer und können anhand der Vor- und Nachteile einschätzen, ob Sie es verwenden möchten oder vielleicht im Einzelfall doch lieber nicht.

Grundlagen der Programmierung: Entwurfsmuster

Erhalten Sie einen fundierten Einstieg in das Thema Entwurfsmuster (Design Patterns) und erfahren Sie, wie Sie Entwurfsmuster in objektorientierten Programmiersprechen umsetzen.

2 Std. 49 min (33 Videos)
Derzeit sind keine Feedbacks vorhanden...
 

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!