Erbauer (Entwurfsmuster)

aus Wikipedia, der freien Enzyklopädie
Wechseln zu: Navigation, Suche

Der Erbauer (englisch builder) ist ein Entwurfsmuster aus dem Bereich der Softwareentwicklung und gehört zur Kategorie der Erzeugungsmuster (creational patterns). Es trennt die Konstruktion komplexer Objekte von deren Repräsentationen, wodurch dieselben Konstruktionsprozesse wiederverwendet werden können.[1] Das Muster ist eines der sogenannten GoF-Muster (Gang of Four, siehe Viererbande).

Verwendung[Bearbeiten]

Softwareentwickler verwenden den Erbauer, wenn

  • zu einem komplexen Objekt unterschiedliche Repräsentationen existieren sollen,
  • die Konstruktion eines komplexen Objekts unabhängig von der Erzeugung der Bestandteile sein soll oder
  • der Konstruktionsablauf einen internen Zustand erfordert, der vor einem Klienten verborgen werden soll.

Typische Anwendungen sind z. B. Applikationen zur Konvertierung.

UML-Diagramm: Erbauer

Akteure[Bearbeiten]

Man kann vier Akteure unterscheiden: Erbauer, KonkreterErbauer, Direktor und Produkt. Der Erbauer spezifiziert eine abstrakte Schnittstelle zur Erzeugung der Teile eines komplexen Objektes. KonkreterErbauer erzeugt die Teile des komplexen Objekts durch Implementierung der Schnittstelle. Außerdem definiert und verwaltet er die von ihm erzeugte Repräsentation des Produkts. Er bietet auch eine Schnittstelle zum Auslesen des Produkts.

Der Direktor konstruiert ein komplexes Objekt unter Verwendung der Schnittstelle des Erbauers. Der Direktor arbeitet eng mit dem Erbauer zusammen: Er weiß, welche Baureihenfolge der Erbauer verträgt oder benötigt. Der Direktor entkoppelt somit den Konstruktionsablauf vom Klienten. Das Produkt repräsentiert das zu konstruierende komplexe Objekt.

Vorteile[Bearbeiten]

Die Implementierungen der Konstruktion und der Repräsentationen werden isoliert. Die Erbauer verstecken ihre interne Repräsentation vor dem Direktor. Neue Repräsentationen lassen sich leicht durch neue konkrete Erbauerklassen einfügen. Der Konstruktionsprozess wird an einer dedizierten Stelle (im Direktor) gesteuert; spätere Änderungen – etwa ein Mehrphasen-Konstruktionsprozess statt einer Einphasen-Konstruktion – lassen sich ohne Änderung der Klienten realisieren.

Nachteile[Bearbeiten]

Es besteht eine enge Kopplung zwischen Produkt, konkretem Erbauer und den am Konstruktionsprozess beteiligten Klassen.[2]

Variante[Bearbeiten]

Man kann auch das Produkt selber die Erbauer-Schnittstelle implementieren lassen. Dadurch erspart man sich u. U. einige Klassen. Das erzeugte Produkt „schleppt“ die Erbauer-Schnittstelle sein ganzes Leben mit sich herum, sodass auch später von außen Produktteile angebaut werden können.

Verwendung in der Analyse[Bearbeiten]

Dieses Muster wird in der Software-Analyse wegen der schwierigen Metapher selten verwendet.

Die Variante, bei der ein Objekt selbst Verfahren zur Verfügung stellt, um weitere Teile „anzubauen“, bewährt sich in pipeline-artigen Geschäftsprozessen. Der Geschäftsprozess als Direktor weist das Dokument als Erbauer an, neue Teile zu erzeugen und in sich einzuhängen. Beispielsweise kann eine Aktenverwaltung in einzelnen Schritten Vermerke an einen „Aktenlauf“ anhängen.

Beispiel[Bearbeiten]

Eine Börsensoftware hält Aktienkurse in einer Textdatei in folgendem Format fest: Pro Aktiengesellschaft werden in einer Zeile, durch Leerzeichen getrennt, Wertpapierkennnummer, Name der Aktiengesellschaft, Kurs und gehandelte Stückzahl gespeichert:

515100 BASF          36,84  2850400
803200 Commerzbank    6,71  17231300
...

Nun soll dieses Format in ein „modernes“ Format wie CSV oder XML umgewandelt werden. Wird im CSV-Format das Semikolon als Trennzeichen benutzt, so soll obige Datei beispielsweise in folgende umgewandelt werden:

515100;BASF;36,84;2850400
803200;Commerzbank;6,71;17231300

Im XML-Format dagegen könnte das Ergebnis der Umwandlung so aussehen:

<Aktienkurse>
        <Aktie>
                <WKN>515100</WKN>
                <Name>BASF</Name>
                <Kurs>36,84</Kurs>
                <Stueckzahl>2850400</Stueckzahl>
        </Aktie>
        <Aktie>
                <WKN>803200</WKN>
                <Name>Commerzbank</Name>
                <Kurs>6,71</Kurs>
                <Stueckzahl>17231300</Stueckzahl>
        </Aktie>
</Aktienkurse>


Das folgende C++-Programm zeigt den Einsatz des Erbauer-Musters in einer Applikation zur Datenformat-Umwandlung, die leicht um weitere Ausgabeformate erweiterbar ist. Der Direktor (Klasse KursdatenLeser) weiß, wie Daten im Altformat einzulesen und zu parsen sind. Er kennt einen Erbauer, der geparste Teile in sein jeweiliges Format übersetzen kann. Alle konkreten Erbauer sind konkrete Unterklassen der abstrakten Klasse KursdatenBauer. Beispielsweise übersetzt die Klasse XMLKursdatenBauer geparste Zeilen in ein XML-Format.

Der Klient kann dem Direktor den konkreten Erbauer zur Laufzeit mitteilen. So kann das Ausgabeformat zur Laufzeit gewechselt werden.

Um ein neues Ausgabeformat zu unterstützen, muss nur die Klasse KursdatenBauer entsprechend durch eine konkrete Unterklasse implementiert werden, z. B. durch LaTeXKursdatenBauer.

Wichtig ist bei diesem Muster Folgendes: Es sind nicht nur die erzeugten Einzelteile, die Komplexität besitzen (darum kümmern sich die konkreten Erzeuger), sondern auch das zu erzeugende Ganze ist ein komplexes Objekt, um dessen Erzeugung sich der Direktor kümmert. Der Direktor ist also der „Fachmann“ für die Erzeugung des Produktes; er alleine kennt die notwendigen Einzelschritte. Im Beispiel weiß er alleine, wie das Altformat zu parsen und daraus das neue Format zusammenzusetzen ist.

#include <iostream>
#include <string>
 
using std::string;
using std::cout;
 
// Abstrakter Erbauer
 
class KursdatenBauer {
public:
  virtual void schreibeKursdaten(const string& wkn, const string& name, 
				 const string& kurs, const string& stueckzahl) 
                                 = 0;
  virtual void initialisiereSchreiben() {}
  virtual void beendeSchreiben() {}
};
 
// Konkreter Erbauer für CSV-Dateien
 
class CSVKursdatenBauer : public KursdatenBauer {
  // Hier entsteht das Produkt, der Einfachheit halber auf die
  // Standardausgabe geschrieben. (Es könnte auch in einen Stream
  // geschrieben werden, der im Konstruktor übergeben wird.)
  virtual void schreibeKursdaten(const string& wkn, const string& name, 
				 const string& kurs, const string& stueckzahl) {
    cout << wkn << ";" << name << ";" 
	 << kurs << ";" << stueckzahl << "\n";
  }  
};
 
// Konkreter Erbauer für XML-Dateien
 
class XMLKursdatenBauer : public KursdatenBauer {
  virtual void schreibeKursdaten(const string& wkn, const string& name, 
				 const string& kurs, const string& stueckzahl) {
    cout << "\t<Aktie>" << "\n";
    cout << "\t\t<WKN>" <<  wkn << "</WKN>\n";
    cout << "\t\t<Name>" << name << "</Name>\n";
    cout << "\t\t<Kurs>" << kurs<< "</Kurs>\n";
    cout << "\t\t<Stueckzahl>" << stueckzahl << "</Stueckzahl>\n";
    cout << "\t</Aktie>\n";
  }  
 
  virtual void initialisiereSchreiben() {
    cout << "<Aktienkurse>" << "\n";
  }
 
  virtual void beendeSchreiben() {
    cout << "</Aktienkurse>" << "\n";
  }
};
 
// Direktor
 
class KursdatenLeser {
private:
  KursdatenBauer* _kursdatenBauer;
public:
  void setKursdatenBauer(KursdatenBauer* kb) {
    _kursdatenBauer = kb;
  }
 
  void parseUndSchreibeKursdaten() {
    _kursdatenBauer->initialisiereSchreiben();
    // lies Zeile für Zeile von STDIN und zerlege in geeignete Teile
    while( ! std::cin.eof() ) {
       string wkn, name, kurs, stueckzahl;
       std::cin >> wkn >> name >> kurs >> stueckzahl;
       if( wkn.empty() ) { break; }
       _kursdatenBauer->schreibeKursdaten(wkn, name, kurs, stueckzahl);
     }
    _kursdatenBauer->beendeSchreiben();
  }
};
 
// Klient
 
int main() {
  CSVKursdatenBauer csvKursdatenBauer;
  XMLKursdatenBauer xmlKursdatenBauer;
  KursdatenLeser    kursdatenLeser;
 
  kursdatenLeser.setKursdatenBauer( &xmlKursdatenBauer );
  // oder
  // kursdatenLeser.setKursdatenBauer( &csvKursdatenBauer );
  kursdatenLeser.parseUndSchreibeKursdaten();
}

Verwandte Entwurfsmuster[Bearbeiten]

Die abstrakte Fabrik ähnelt dem Erbauer, weil sie ebenfalls komplexe Objekte erzeugen kann. Dabei steht aber nicht die Struktur im Vordergrund, sondern die Abstraktion vom konkreten Typ der erzeugten Objekte. Der Erbauer erzeugt oft ein Kompositum (Entwurfsmuster). Bei Applikationen zur Konvertierung ist der Direktor – oder sogar der Erbauer – oft ein Visitor (Besucher) oder eventuell ein Interpreter (Entwurfsmuster) der Struktur, die konvertiert werden soll.

Einzelnachweise[Bearbeiten]

  1.  Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides: Entwurfsmuster. 5 Auflage. Addison-Wesley, 1996, ISBN 3-8273-1862-9, S. 119.
  2.  Karl Eilebrecht, Gernot Starke: Patterns kompakt. Entwurfsmuster für effektive Software-Entwicklung. 3 Auflage. Spektrum Akademischer Verlag, 2010, ISBN 978-3-8274-2525-6, S. 29, doi:10.1007/978-3-8274-2526-3.

Weblinks[Bearbeiten]