- Factory Pattern
-
Der Begriff Fabrikmethode (englisch Factory Method) bezeichnet ein Entwurfsmuster (engl. Design Pattern) aus dem Bereich der Softwareentwicklung. Das Muster beschreibt, wie ein Objekt durch Aufruf einer Methode anstatt durch direkten Aufruf eines Konstruktors erzeugt wird. Es gehört somit zur Kategorie der Erzeugungsmuster (engl. Creational Patterns).
Der Begriff Fabrikmethode kann jedoch insofern missverständlich sein, als er je nach Sprecher zwei leicht unterschiedliche Entwurfsmuster bezeichnet.
Inhaltsverzeichnis
Formal korrekte Bezeichnung
Korrekterweise bezeichnet der Begriff Fabrikmethode ein Entwurfsmuster, bei dem die Schnittstelle zur Erstellung eines Objektes eine (abstrakte) Methode einer Oberklasse ist. Die konkrete Implementierung der Erzeugung neuer Objekte findet jedoch nicht in der Oberklasse statt, sondern in von ihr abgeleiteten Unterklassen, die die besagte abstrakte Methode implementieren oder überschreiben.
Das Muster beschreibt somit die Erzeugung von Objekten, wenn die Unterklassen selbst bestimmen, von welchen Klassen die zu erzeugenden Objekte sind. Es ist eines der sogenannten GoF-Muster (Gang of Four, siehe Viererbande). Dieses Muster wird manchmal auch als virtueller Konstruktor (virtual constructor) bezeichnet.
Beispiel (in Java):
abstract class Erzeuger { /* Die Oberklasse definiert die Schnittstelle zur Erzeugung, bietet aber keine konkrete Implementierung: */ public abstract Produkt erzeugeProdukt(); //←Das ist die Fabrikmethode. } class KonkreterErzeugerA extends Erzeuger { /* Die Objekte werden stattdessen in den Unterklassen erzeugt. Häufig sind diese Objekte dann auch von einem spezielleren Typ als demjenigen, der von der Oberklasse vorgegeben ist. */ public Produkt erzeugeProdukt() { return new KonkretesProdukt1(); //KonkretesProdukt1 ist eine Unterklasse von Produkt } } class KonkreterErzeugerB extends Erzeuger { public Produkt erzeugeProdukt() { return new KonkretesProdukt2(); //KonkretesProdukt2 ist eine Unterklasse von Produkt } }
Umgangssprachliche Bezeichnung
Der Begriff „Fabrikmethode“ wird in der Praxis auch oft einfach nur für eine statische Methode verwendet, die ein neues Objekt erzeugt, vergleichbar einem Konstruktor.
Beispiel: Statt
SomeObject o = new SomeObject();
wird unter Verwendung der umgangssprachlich als „Fabrikmethode“ bezeichneten statischen Methode geschrieben:
SomeObject o = SomeObjectFactory.createNewInstance();
In diesem Fall ist keine Verwendung von Unterklassen bzw. Polymorphismus vorgesehen.
Diese Verwendung des Begriffes Fabrikmethode ist jedoch nicht korrekt.
Verwendung
Die Fabrikmethode (in der formal korrekten Bedeutung) findet Anwendung, wenn eine Klasse die von ihr zu erzeugenden Objekte nicht kennen kann bzw. soll (1), (2) oder Unterklassen bestimmen sollen, welche Objekte erzeugt werden (nur 1)). Typische Anwendungsfälle sind Frameworks und Klassenbibliotheken.
UML-Diagramm
Das folgende Klassendiagramm zeigt die vier am Entwurfsmuster beteiligten Rollen. Konkreter Erzeuger erbt die Fabrikmethode von Erzeuger und implementiert sie so, dass sie KonkretesProdukt erzeugt, das wiederum Produkt spezialisiert.
Akteure
Das Produkt ist der Basistyp (Klasse oder Schnittstelle) für das zu erzeugende Produkt. Der Erzeuger deklariert die Fabrikmethode, um ein solches Produkt zu erzeugen und kann eine Default-Implementation beinhalten. Mitunter wird für die Fabrikmethode eine Implementierung vorgegeben, die ein „Standard-Produkt“ erzeugt.
Das KonkreteProdukt implementiert die Produkt-Schnittstelle (Subtyp von Produkt). Der KonkreteErzeuger (nur bei 1) überschreibt die Fabrikmethode um konkretere Produkte zu erzeugen und determiniert damit das konkrete Produkt (z. B. indem er den Konstruktor einer konkreten Klasse aufruft).
Vorteile
Fabrikmethoden entkoppeln ihre Aufrufer von Implementierungen konkreter Produkt-Klassen. Das ist insbesondere wertvoll, wenn Frameworks sich während der Lebenszeit einer Applikation weiterentwickeln - so können zu einem späteren Zeitpunkt Instanzen anderer Klassen erzeugt werden, ohne dass sich die Applikation ändern muss.
In C++, Java und ähnlichen Sprachen kann eine Fabrikmethode im Gegensatz zu einem Konstruktor einen aussagefähigeren Namen haben, z. B. Color.createRGB(...) vs. Color.createHSB(...).
Nachteile
Die Verwendung dieses Erzeugungsmusters läuft auf Unterklassenbildung hinaus. Es muss eine eigene Klasse vorhanden sein, die die statische Methode aufnehmen kann (das hat schon zu Forderungen geführt, dass in Java- oder C#-Schnittstellen statische Methoden erlaubt werden sollten).
Beispiele
1) Virtuelle Methode in Interface oder Klasse (z. B. Fassade), die auch sonst für Objekte eines Typs zuständig ist. Unterklassen können dann spezifische Typen erzeugen. Typische Szenarien:
1.1. Erzeugen abhängiger Objekte. Beispiele:
- Java: java.sql.Connection.createStatement() - das erzeugte Statement verweist auf die Connection und „lebt in dieser“.
- .Net: System.Data.IDbConnection.CreateCommand() - das erzeugte IDbCommand verweist auf die Connection und „lebt in dieser“.
Oft haben die erzeugten abhängigen Objekte wieder Factory-Methoden für davon abhängige Objekte, z. B. hat IDbCommand eine Methode CreateParameter(). Daher lassen sich Klassen mit solchen Factory-Methoden nicht als „Factory-Klassen“ (mit Hauptverantwortung „Object Creation“) verstehen - im Unterschied zur abstrakten Fabrik.
1.2. Erzeugen unabhängiger Objekte über zentralisierte „indizierte Konstruktoren“: Eine Methode aus einer Familie von Factory-Methoden wird mit Hilfe eines Dictionaries über einen Key aufgerufen. Code-Snippet (mit C#-delegates statt Unterklassen - der Delegate-Typ repräsentiert den Erzeuger, jede konkrete anonyme Methode jeweils einen KonkretenErzeuger):
delegate IFoo CreateFoo(IContext creationParameter); static IDictionary<Key, CreateFoo> fooFactory = new Dictionary<Key, CreateFoo>(); // Statische Initialisierung: fooFactory.Add(key1, delegate(IContext cp) { return new FooForKey1(cp); }); fooFactory.Add(key2, delegate(IContext cp) { return new FooForKey2Or3(new Key2Child(cp)); }); fooFactory.Add(key3, delegate(IContext cp) { return new FooForKey2Or3(new Key3Child(cp)); });
Aufruf:
IFoo newObject = fooFactory[key](someContext);
Erlaubt ein kompaktes, deskriptives Design der Objekterzeugung. Gefahr (insbesondere, wenn - z. B. in C# - im Dictionary direkt auf Funktionsaufrufe verwiesen wird), dass die Factory-Objekte mehr Verantwortung übernehmen.
2) „Static Factory Method“: Einzelne static-Methode, die ein Objekt eines Typs oder Unter-Typs zurückliefert. Kein „virtual constructor“ - Sinn der Sache: Zentraler, klassenbasierter Access Point für Objekterzeugung analog zu new. Erfordert manchmal Einführung einer einzelnen Klasse nur als „Factory Method Holder“. Beispiele:
- Java: java.util.Collections.singletonMap()
- Java: javax.xml.parsers.DocumentBuilderFactory.newInstance()
Verwandte Entwurfsmuster
Eine abstrakte Fabrik (Abstract Factory) wird i. A. mittels Fabrikmethoden realisiert.
Fabrikmethoden werden typischerweise aus Schablonenmethoden (Template Method) heraus aufgerufen.
Fabrikmethoden finden sich oft in Singletons.
Weblinks
- Die Fabrikmethode in PHP (englisch)
- Fabrikmethode in C# (englisch)
- Beispiel für die Fabrikmethode in Java (deutsch)
- Fabrikmethode in Java (englisch)
- Factory Method (englisch)
- Fabrikmethode in Java und .NET (englisch)
Erzeugungsmuster: Abstrakte Fabrik | Singleton | Builder | Fabrikmethode | Prototyp
Strukturmuster: Adapter | Brücke | Decorator | Facade | Flyweight | Kompositum | Stellvertreter
Verhaltensmuster: Observer | Visitor | Interpreter | Iterator | Kommando | Memento | Schablonenmethode | Strategie | Vermittler | Zustand | Zuständigkeitskette
(Klassenmuster sind kursiv dargestellt)
Wikimedia Foundation.