Factory-Muster (Fabrik)
Kurz: Eine Factory kapselt die Erzeugung von Objekten: Der Aufrufer sagt, was er braucht, und die Fabrik entscheidet, welche konkrete Klasse instanziiert wird.
Genauer: Dadurch hängt der Aufrufer nur von einer Schnittstelle ab (Polymorphie), nicht von konkreten Klassen. Neue Varianten lassen sich an einer Stelle ergänzen. Es gibt die einfache Fabrikmethode sowie die Abstrakte Fabrik, die ganze Familien zusammengehöriger Objekte erzeugt.
Im Detail
class Hund:
def laut(self): return "Wau"
class Katze:
def laut(self): return "Miau"
def tier_fabrik(art):
tiere = {"hund": Hund, "katze": Katze}
if art not in tiere:
raise ValueError(f"Unbekannte Art: {art}")
return tiere[art]()
print(tier_fabrik("hund").laut()) # Wau
print(tier_fabrik("katze").laut()) # Miauinterface Zahlung { void zahle(double betrag); }
class Kreditkarte implements Zahlung { public void zahle(double b) { /* ... */ } }
class Paypal implements Zahlung { public void zahle(double b) { /* ... */ } }
class ZahlungFactory {
static Zahlung erzeuge(String art) {
return switch (art) {
case "kreditkarte" -> new Kreditkarte();
case "paypal" -> new Paypal();
default -> throw new IllegalArgumentException(art);
};
}
}Wann sinnvoll?
- Die Auswahl der Klasse hängt von Konfiguration oder Eingaben ab.
- Die Erzeugung ist aufwendig (viele Parameter, Abhängigkeiten).
- Man möchte beim Testen Attrappen einschleusen (Dependency Injection).
Nicht jede Erzeugung braucht eine Fabrik: new Hund() ist völlig in Ordnung, solange es nur eine Variante gibt. Mit dem Singleton teilt die Factory die Eigenschaft, dass sie zu den Erzeugungsmustern gehört; das Builder-Muster ist eine Verwandte für Objekte mit vielen optionalen Eigenschaften.
Siehe auch: Singleton, Polymorphie, Dependency Injection, Schnittstelle