Entwurfsmuster: Erzeugungsmuster Erzeugungsmethode

Ein Objekt von einer konkreten Klasse zu erzeugen kann in manchen Fällen komplizierter und unverständlicher sein, als es eigentlich notwendig ist. Auch wenn es soweit wie möglich zu vermeiden ist, werden hin und wieder im Konstruktor überflüssige null Parameter zu Erzeugung neuer Objekte benötigt. Dies sind meist optionale Parameter, die nur für eine bestimmte Art von Klassenobjekt benötigt werden.
Um die Objekterzeugung nicht unnötig zu verkomplizieren und undurchschaubar zu machen, gibt es das Erzeugungsmuster Erzeugungsmethode.

Mit Hilfe der Erzeugungsmethoden wird eine klare und saubere Trennung unterschiedlicher Objekte gewährleistet. Um dies zu garantieren, darf es zunächst keinen öffentlichen Konstruktor geben. Die Objekte werden von außerhalb über öffentliche statische Methoden konstruiert, welche gegebenenfalls die privaten Konstruktoren aufrufen. Betrachten wir für das Verständnis folgendes kleines aus der Luft gegriffenes Beispiel:

Über die Klasse RaceCircuit kann ein Fahrt auf einer Rennstrecke erstellt werden. Zur Auswahl stehen in diesem Beispiel zwei unterschiedliche Arten von Kraftfahrzeugen zur Verfügung. Ein Auto sowie ein Motorrad. Es kann aber natürlich beim Aufruf des Konstruktors nur ein Auto oder ein Motorrad angegeben werden. Der öffentliche Konstruktor sieht wie folgt aus.

/** öffentlicher Konstruktor */
public RaceCircuit(String raceCircuitName, 
				   int rounds, 
				   Car car, 
				   Motorbike motorbike)

Um ein Objekt zu erzeugen wird der Name der Rennstrecke, die Anzahl der Runden und das Auto, oder aber das Motorrad benötigt. Da wir nun wissen, das es entweder ein Auto oder ein Motorrad sein kann, würde ein Objekterzeugung in etwa wie folgt aussehen:

// Auto
new RaceCircuit("Nürburgring", 4, car, null);

// Motorrad
new RaceCircuit("Oschersleben", 10, null, motorbike);

Es fällt auf, das entweder der car– oder aber der motorbike Paramter null ist (sein muss). Dennoch müssen in diesem Fall immer alle vier Parameter dem Konstruktor übergeben werden, obwohl eigentlich nur drei notwendig sind. Zusätzlich müsste bei einer sauberen Implementierung noch im Rumpf des Konstruktors zu Anfang überprüft werden, ob wirklich genau eines der beiden Parameter null ist. Ist dies nicht der Fall, sollte eine Exception geworfen werden, da ein ungültiges Objekt erzeugt werden soll.

Um die Lesbarkeit zu erhöhen und die Konstruktionssicherheit zu gewährleisten, werden zwei öffentliche statische (Erzeugungs)Methoden erzeugt und der Konstrukor als private deklariert.

/** private Konstruktor */
private RaceCircuit(String raceCircuitName, 
				   int rounds, 
				   Car car, 
				   Motorbike motorbike)
	{ /** ... */}
	
/** Erzeugt ein Auto */
public RaceCircuit createCarRound(String raceCircuitName, 
		   int rounds, 
		   Car car)
{
	return new RaceCircuit(raceCircuitName, rounds, car, null);
}

/** Erzeugt ein Motorrad */
public RaceCircuit createMotorbikeRound(String raceCircuitName, 
		   int rounds, 
		   Motorbike motorbike)
{
	return new RaceCircuit(raceCircuitName, rounds, null, motorbike);
}

Soll nun ein Runde auf der Rennstrecke mit einem Auto oder einem Motorrad erzeugt werden, sieht der Aufruf wie folgt aus:

RaceCircuit.createCarRound("Nürburgring", 4, car);
RaceCircuit.createMotorbikeRound("Oschersleben", 10, motorbike);

Durch die beiden Erzeugungsmethoden entfällt der Prüfung auf null Werte sowie die überflüssige Übergabe des vierten Parameters. Zusätzlich ist nun die Gefahr der Erzeugung eines ungültigen Objekts minimiert worden.

Update: Durch die Anregungen der Leser in den Artikelkommentaren möchte ich folgendes ergänzen (vielen Dank für die Hinweise). Das hier gezeigte Beispiel soll die Verwendung des Erzeugungsmusters verdeutlichen. Aus diesem Grund wird auf eine Abstrahierung der Klasse Car und und Motorbike verzichtet. In einem Produktivumfeld wäre dies natürlich unabdingbar. Des Weiteren ist es zu erwähnen, das die hier gezeigte Konstruktoränderung in die Erzeugungsmethoden durchaus auch über zwei verschiedene Konstruktoren hätte gelöst werden können, jedoch würde dann der Sinn der Erzeugungsmethode entfallen. Die Erzeugungsmethode dient unter anderem dafür, durch hilfreiche Methodennamen das Studieren der verschiedenen Kontsruktoren zu vermeiden. Dies erleichtert somit die Lesbarkeit des Codes.