Mehr als 500.000 Exemplare sind von „Design Patterns: Elements of Reusable Object-Oriented Software“ seit der Ver­öf­fent­li­chung im Jahr 1994 verkauft worden. Das Buch für Software-Ent­wick­ler be­schreibt 23 ver­schie­den­ar­ti­ge Design Patterns, die in Fach­krei­sen auch als „Gang of Four“-Design-Patterns („Vie­rer­ban­de“-Ent­wurfs­mus­ter) bekannt sind – eine Be­zeich­nung, die auf die vier Autoren Erich Gamma, John Vlissides, Ralph Johnson und Richard Helm zu­rück­geht.

Zu den zahl­rei­chen Design-Stra­te­gien, die im Rahmen dieses Werks ver­mit­telt werden, zählt auch die so­ge­nann­te Fa­brik­me­tho­de (engl. factory method), die es einer Klasse er­mög­licht, die Erzeugung von Objekten an Sub­klas­sen zu de­le­gie­ren. Konkrete In­for­ma­tio­nen zur Nutzung dieser prak­ti­schen Methode liefert ins­be­son­de­re das Factory Method Pattern, das heute häufig einfach als Factory Pattern be­zeich­net wird.

Was ist das Factory Pattern (Factory Method Pattern)?

Das Factory Method Pattern be­schreibt einen Pro­gram­mier­an­satz, nach dem sich Objekte kreieren lassen, ohne die exakte Klasse dieser Objekte spe­zi­fi­zie­ren zu müssen. Dadurch lässt sich das erstellte Objekt flexibel und bequem aus­tau­schen. Für die Umsetzung greifen Ent­wick­ler dabei auf die na­mens­ge­ben­de Factory Method zurück, zu Deutsch Fa­brik­me­tho­de. Diese wird wahlweise in einer Schnitt­stel­le spe­zi­fi­ziert und per Child-Klasse im­ple­men­tiert oder per Ba­sis­klas­se im­ple­men­tiert und optional über­schrie­ben (von ab­ge­lei­te­ten Klassen). Das Pattern bzw. die Methode rücken damit an die Stelle der regulären Klassen-Kon­struk­tors, um die Erzeugung von Objekten von den Objekten selbst zu lösen und so ein Befolgen der SOLID-Prin­zi­pi­en zu er­mög­li­chen.

Hinweis

Die SOLID-Prin­zi­pi­en sind eine Teil­grup­pe der Prin­zi­pi­en ob­jekt­ori­en­tier­ten Designs, die den Ent­wick­lungs­pro­zess ob­jekt­ori­en­tier­ter Software ver­bes­sern sollen. Das Akronym „SOLID“ steht dabei für folgende fünf Prin­zi­pi­en:

  • Single-Re­spon­si­bi­li­ty-Prinzip: Jede Klasse soll nur eine einzige Ver­ant­wor­tung besitzen.
  • Open-Closed-Prinzip: Software-Einheiten sollen er­wei­ter­bar sein, ohne hierfür ihr Verhalten ändern zu müssen.
  • Lis­kov­sches Sub­sti­tu­ti­ons­prin­zip: Eine ab­ge­lei­te­te Klasse soll stets anstelle ihrer Ba­sis­klas­se ein­setz­bar sein.
  • Interface-Se­gre­ga­ti­on-Prinzip: In­ter­faces sollen perfekt auf die An­for­de­run­gen der zu­grei­fen­den Clients ab­ge­stimmt sein.
  • Dependency-Inversion-Prinzip: Klassen auf einem höheren Abs­trak­ti­ons­le­vel sollen niemals von Klassen eines nied­ri­ge­ren Abs­trak­ti­ons­le­vels abhängig sein.

Anstelle der üblichen Be­zeich­nung nutzt man heute in vielen Fällen den ver­kürz­ten Begriff Factory Pattern (dt. Factory-Muster) bzw. Factory Design Pattern (dt. Factory-Ent­wurfs­mus­te), wobei dieser im GoF-Werk nicht zu finden ist. Bei einem Blick in das Buch finden Sie neben dem hier the­ma­ti­sier­ten Factory Method Pattern lediglich das ähnliche Abstract Factory Pattern, das eine Schnitt­stel­le zur Kreation einer Familie von Objekten definiert, deren konkrete Klassen erst während der Laufzeit fest­ge­legt werden.

Welches Ziel verfolgt das Factory Design Pattern?

Das Factory Pattern will ein grund­le­gen­des Problem bei der In­stan­zi­ie­rung – also der Kreation eines konkreten Objekts einer Klasse – in der ob­jekt­ori­en­tier­ten Pro­gram­mie­rung lösen: Ein Objekt direkt innerhalb der Klasse zu erstellen, die dieses Objekt benötigt bzw. verwenden soll, ist prin­zi­pi­ell möglich, aber sehr un­fle­xi­bel. Es bindet die Klasse an dieses bestimmte Objekt und macht es unmöglich, die In­stan­zi­ie­rung un­ab­hän­gig von der Klasse zu verändern. Der­ar­ti­ger Code wird durch den Factory-Pattern-Ansatz vermieden, indem hier zunächst eine separate Operation für das Erstellen des Objekts definiert wird – die Factory-Methode. Sobald diese auf­ge­ru­fen wird, generiert sie das Objekt, anstelle des bereits erwähnten Klassen-Kon­struk­tors.

Factory Pattern: UML-Diagramm des Factory-Ent­wurfs­mus­ters

In Software, die sich an dem Factory Design Pattern ori­en­tiert, wird der Code eines zu er­stel­len­den Objekts (in diesem Zu­sam­men­hang auch als „Produkt“ be­zeich­net) also separat in eine eigene Klasse aus­ge­la­gert. Diese abstrakte Klasse, auch „Creator“ oder – passend zum Pattern – „Factory“ (dt. Fabrik) genannt, delegiert die Ob­jekt­in­stan­zi­ie­rung ih­rer­seits an eine Un­ter­klas­se (Con­cre­te­Crea­tor), die letztlich darüber ent­schei­det, welches Produkt erstellt wird. Hierfür übernimmt der Con­cre­te­Crea­tor die Methode crea­te­Pro­duct() und gibt an­schlie­ßend ein Con­cre­te­Pro­dukt zurück, das optional vom Creator mit Her­stel­lungs­code erweitert werden kann, bevor es als fertiges Produkt an die Schnitt­stel­le übergeben wird.

Deut­li­cher wird der Prozess im nach­fol­gen­den UML-Klas­sen­dia­gramm des Factory Patterns, das die ge­schil­der­ten Zu­sam­men­hän­ge und Vorgänge grafisch zu­sam­men­fasst.

Die Vor- und Nachteile des Factory Design Patterns

Der Aufruf einer Pro­gramm­me­tho­de wird beim Factory Pattern gänzlich von der Im­ple­men­tie­rung neuer Klassen separiert, was einige Vorzüge mit sich bringt. So wirkt sich dieser Umstand ins­be­son­de­re auf die Er­wei­ter­bar­keit einer Software aus: Factory-Instanzen besitzen ein hohes Maß an Ei­gen­stän­dig­keit und erlauben das Hin­zu­fü­gen neuer Klassen, ohne dass sich die Ap­pli­ka­ti­on hierfür in ir­gend­ei­ner Weise ändern muss – parallel zur Laufzeit. Es genügt, die Factory-Schnitt­stel­le zu im­ple­men­tie­ren und den Creator ent­spre­chend zu in­stan­zi­ie­ren (via Con­cre­te­Crea­tor).

Ein weiterer Vorteil besteht in der guten Test­bar­keit der Factory-Kom­po­nen­ten. Im­ple­men­tiert ein Creator bei­spiels­wei­se drei Klassen, so lässt sich deren Funk­tio­na­li­tät einzeln und un­ab­hän­gig von der auf­ru­fen­den Klasse testen. Bei letzterer ist lediglich si­cher­zu­stel­len, dass sie den Creator ord­nungs­ge­mäß aufruft, selbst wenn die Software an dieser Stelle zu einem späteren Zeitpunkt erweitert wird. Ebenfalls vor­teil­haft ist die Mög­lich­keit, Fa­brik­me­tho­den (anders als bei einem Klassen-Kon­struk­tor) mit einem aus­sa­ge­kräf­ti­gen Namen versehen zu können.

Die große Schwäche des Factory Design Patterns ist die Tatsache, dass seine Umsetzung zu einem starken Anstieg der ein­ge­bun­de­nen Klassen führt, denn jedes Con­cre­te­Pro­dukt erfordert immer auch einen Con­cre­te­Crea­tor. So ge­winn­brin­gend der Factory-Ansatz hin­sicht­lich der Er­wei­te­rung einer Software grund­sätz­lich ist, so nach­teil­haft ist er außerdem, wenn es um den auf­zu­brin­gen­den Aufwand geht: Soll eine Pro­dukt­fa­mi­lie ergänzt werden, müssen nicht nur die Schnitt­stel­le, sondern auch alle un­ter­ge­ord­ne­ten Con­cre­te­Crea­tor-Klassen ent­spre­chend angepasst werden. Eine gute Vor­aus­pla­nung hin­sicht­lich der be­nö­tig­ten Pro­dukt­ty­pen ist folglich un­ver­zicht­bar.

Vorteile Nachteile
Modulare Er­wei­ter­bar­keit der Ap­pli­ka­ti­on Hohe Zahl an er­for­der­li­chen Klassen
Gute Test­bar­keit Er­wei­te­rung der Ap­pli­ka­ti­on ist sehr aufwendig
Aus­sa­ge­kräf­ti­ge Methoden-Namen  

Wo wird das Factory Method Pattern ein­ge­setzt?

Das Factory Pattern kann sich in ver­schie­de­nen An­wen­dungs­sze­na­ri­en als wertvoll erweisen. Ins­be­son­de­re Software, bei der die konkret zu er­stel­len­den Produkte nicht bekannt sind bzw. nicht im Vorhinein definiert werden, pro­fi­tiert von dem al­ter­na­ti­ven Ansatz für das Sub­klas­sen-Ma­nage­ment. Typische An­wen­dungs­fäl­le sind daher Frame­works oder Klas­sen­bi­blio­the­ken, die als Grund­ge­rüst für die Ent­wick­lung moderner Ap­pli­ka­tio­nen quasi un­ver­zicht­bar geworden sind.

Auch Au­then­ti­fi­zie­rungs­sys­te­me pro­fi­tie­ren von den Vorzügen des Factory Design Patterns: Anstelle einer zentralen Klasse mit diversen Pa­ra­me­tern, die je nach Nut­zer­be­rech­ti­gung variieren, lässt sich hier der Au­then­ti­fi­zie­rungs­pro­zess an Factory-Klassen de­le­gie­ren, die ei­gen­stän­dig Ent­schei­dun­gen über das Handling des je­wei­li­gen Users treffen.

Zudem eignet sich das Design nach dem Factory-Pattern-Ansatz generell natürlich für sämtliche Software, in der planmäßig und in aller Re­gel­mä­ßig­keit neue Klassen hin­zu­ge­fügt werden – ins­be­son­de­re, wenn diese Klassen den gleichen Er­stel­lungs­pro­zess durch­lau­fen müssen.

Factory Pattern: Beispiel (PHP)

Das Factory-Ent­wurfs­mus­ter kann in Ap­pli­ka­tio­nen ver­schie­dens­ter Pro­gram­mier­spra­chen zum Einsatz kommen. Zu den be­kann­tes­ten Ver­tre­tern zählen dabei Java, Ja­va­Script, C++, C#, Python und PHP. Letzt­ge­nann­te Skript­spra­che kommt auch im nach­fol­gen­den Pra­xis­bei­spiel, bei dem wir uns an folgendem Artikel im Blog Phpm­on­keys ori­en­tie­ren, zum Einsatz.

Gesetzt ist in diesem Fall ein Szenario mit der abs­trak­ten Klasse „Car“ (Creator) und der Factory-Klasse „Car­Fac­to­ry“ (Con­cre­te­Crea­tor). Erstere ist möglichst simpel gestaltet und enthält lediglich Code, um eine Farbe für das Auto zu setzen – Stan­dard­far­be: weiß – und diese aus­zu­le­sen:

class Car {
	private $color = null;
	public function __construct() {
		$this->color = "white";
	}
	public function setColor($color) {
		$this->color = $color;
	}
	public function getColor() {
		return $this->color;
	}
}

In der Factory-Klasse werden zudem Methoden für „rote“ (red) und „blaue“ (blue) Autos sowie eine private Methode für die ei­gent­li­che Klas­sen­er­stel­lung ein­ge­führt:

class CarFactory {
	private function __construct() {
	}
	public static function getBlueCar() {
		return self::getCar("blue");
	}
	public static function getRedCar() {
		return self::getCar("red");
	}
	private static function getCar($color) {
		$car = new Car();
		$car->setColor($color);
		return $car;
	}
}

Wahlweise lässt sich diese noch sehr über­sicht­li­che Factory-Klasse nun – dank dem Factory Method Pattern bzw. der Fa­brik­me­tho­de – noch mit den ver­schie­dens­ten weiteren Au­to­merk­ma­len wie weiteren Farben, der Automarke oder dem Preis erweitern.

Zum Hauptmenü