Factory-Muster
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 72 von 91.
Das Factory Pattern ist ein Muster zur Objekterzeugung, das die Erstellung von Objekten an eine separate Klasse oder Methode delegiert. Anstatt new direkt in deinem gesamten Code zu verwenden, bittest du eine Factory, Objekte für dich zu erstellen.
Dieses Muster ist besonders nützlich, wenn du mehrere verwandte Klassen hast, die eine gemeinsame Schnittstelle teilen, und du anhand einer Bedingung entscheiden möchtest, welche davon instanziiert werden soll. Betrachte ein Benachrichtigungssystem, das Nachrichten über verschiedene Kanäle senden kann:
<?php
interface Notification {
public function send(string $message): string;
}
class EmailNotification implements Notification {
public function send(string $message): string {
return "Email: $message";
}
}
class SmsNotification implements Notification {
public function send(string $message): string {
return "SMS: $message";
}
}
Ohne eine Factory würdest du überall if-Anweisungen und new-Aufrufe verstreuen. Die Factory zentralisiert diese Logik:
<?php
class NotificationFactory {
public static function create(string $type): Notification {
return match($type) {
'email' => new EmailNotification(),
'sms' => new SmsNotification(),
default => throw new InvalidArgumentException("Unknown type: $type")
};
}
}
$notification = NotificationFactory::create('email');
echo $notification->send('Hello!');
Ausgabe:
Email: Hello!Der entscheidende Vorteil besteht darin, dass dein Code von der Schnittstelle Notification und nicht von konkreten Klassen abhängt. Wenn du später eine Klasse PushNotification hinzufügst, musst du nur die Factory aktualisieren. Der gesamte Code, der die Factory verwendet, erhält automatisch Zugriff auf den neuen Typ, ohne dass Änderungen erforderlich sind.
Aufgabe
EinfachErstellen wir ein Dokumentgeneratorsystem mit dem Fabrikmuster. Verschiedene Dokumenttypen (PDF, HTML, Klartext) verwenden eine gemeinsame Schnittstelle, erzeugen aber unterschiedliche Ausgaben: ein perfektes Szenario, um die Objekterstellung in einer Factory zu zentralisieren.
Du organisierst deinen Code auf vier Dateien verteilt:
Document.php: Erstelle eineDocument-Schnittstelle, die den Vertrag definiert, den alle Dokumenttypen einhalten müssen. Sie sollte eine einzige Methoderender(string $content): stringbesitzen, die Inhalte entgegennimmt und die formatierten Dokumentausgaben zurückgibt.Documents.php: Binde die Document-Schnittstelle ein und erstelle drei Klassen, die sie implementieren:PdfDocument: Die Methoderender()gibt"PDF: [content]"zurückHtmlDocument: Die Methoderender()gibt"<html>[content]</html>"zurückTextDocument: Die Methoderender()gibt"TXT: [content]"zurück
DocumentFactory.php: Binde die Documents-Datei ein und erstelle eineDocumentFactory-Klasse mit einer statischen Methodecreate(string $type): Document. Diese Methode solltematchverwenden, um abhängig vom Typ das passende Dokumentobjekt zurückzugeben:"pdf"gibt ein neuesPdfDocumentzurück"html"gibt ein neuesHtmlDocumentzurück"text"gibt ein neuesTextDocumentzurück- Bei jedem anderen Typ soll eine
InvalidArgumentExceptionmit der Nachricht"Unknown document type: [type]"ausgelöst werden
main.php: Binde die DocumentFactory-Datei ein. Du erhältst zwei Eingaben: einen Dokumenttyp und den zu rendernden Inhalt.Verwende die Factory, um den passenden Dokumenttyp zu erstellen, rufe anschließend seine Methode
render()mit dem Inhalt auf und gib das Ergebnis aus.Gib in einer neuen Zeile
"Factory benefit: Adding new types only requires updating the factory"aus, um hervorzuheben, warum dieses Muster wertvoll ist.
Das Fabrikmuster hält deinen Code flexibel. Wenn du später ein MarkdownDocument hinzufügen musst, aktualisierst du nur die Factory, während der gesamte bestehende Code unverändert weiter funktioniert.
Probier es selbst
<?php
require_once 'DocumentFactory.php';
// Eingabe lesen
$type = trim(fgets(STDIN));
$content = trim(fgets(STDIN));
// TODO: Verwende DocumentFactory, um den entsprechenden Dokumenttyp zu erstellen
// TODO: Rufe die render()-Methode mit dem Inhalt auf und gib das Ergebnis aus
// TODO: On a new line, print "Factory benefit: Adding new types only requires updating the factory"
?>Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in OOPKlassen vs. ObjekteDas Schlüsselwort $thisMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick – Einfacher Taschenrechner4Vererbung
Grundlegende VererbungDas Schlüsselwort parent::MethodenüberschreibungDas Schlüsselwort finalAbstrakte KlassenRückblick – Mitarbeiterhierarchie7Kapselung
Öffentlich, geschützt, privatZugriffsmodifikatoren im DetailGetter und SetterInformationsverbergungKonstruktor-Promotion (8.0)Wiederholung – System zur Verwaltung von Schülerdatensätzen2Namespaces & Autoloading
Einführung in NamespacesDas use-SchlüsselwortPSR-4-Autoloading-StandardComposer-AutoloaderRückblick – Organisiertes Projekt5Schnittstellen & Verträge
Einführung in SchnittstellenSchnittstellen implementierenMehrere Schnittstellen implementierenSchnittstelle vs. abstrakte KlasseTyp-Hinweise mit SchnittstellenRückblick – Formrechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objektklonen__serialize & __unserializeRückblick – Benutzerdefinierte Sammlung11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenBenutzerdefinierte Exception-HierarchieTry, Catch, FinallyRückblick – Formularvalidator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klassen-Eigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenSchreibgeschützte Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphie
Methodenüberschreibung erneut betrachtetPolymorphie über SchnittstellenTyp-Hinweise & Union-TypenSpätes statisches BindenRückblick – Zahlungsabwickler9Traits
Einführung in TraitsMehrere Traits verwendenAuflösung von Trait-KonfliktenAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungÜbe selbstständig: Online-PHP-Compiler