Menu
Coddy logo textTech

Factory-Muster

Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 72 von 91.

Das Factory Pattern ist ein Erzeugungsmuster, das die Objekterzeugung an eine separate Klasse oder Methode delegiert. Anstatt new direkt in Ihrem gesamten Code zu verwenden, bitten Sie eine Factory, Objekte für Sie zu erstellen.

Dieses Muster ist besonders nützlich, wenn Sie mehrere verwandte Klassen haben, die eine gemeinsame Schnittstelle teilen, und Sie entscheiden möchten, welche davon basierend auf einer bestimmten Bedingung instanziiert werden soll. Stellen Sie sich ein Benachrichtigungssystem vor, 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ürden Sie if-Anweisungen und new-Aufrufe überall verteilen. 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 ist, dass Ihr Code von dem Notification Interface abhängt und nicht von konkreten Klassen. Wenn Sie später eine PushNotification Klasse hinzufügen, aktualisieren Sie nur die Factory. Der gesamte Code, der die Factory verwendet, erhält automatisch Zugriff auf den neuen Typ, ohne dass Änderungen erforderlich sind.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Dokumentengenerierungssystem mit dem Factory Pattern erstellen. Verschiedene Dokumenttypen (PDF, HTML, Plain Text) teilen sich ein gemeinsames Interface, erzeugen aber unterschiedliche Ausgaben — ein perfektes Szenario, um die Objekterstellung in einer Factory zu zentralisieren.

Sie werden Ihren Code über vier Dateien organisieren:

  • Document.php — Erstellen Sie ein Document Interface, das den Vertrag definiert, dem alle Dokumenttypen folgen müssen. Es sollte eine einzige Methode render(string $content): string haben, die den Inhalt entgegennimmt und die formatierte Dokumentenausgabe zurückgibt.
  • Documents.php — Binden Sie das Document-Interface ein und erstellen Sie drei Klassen, die es implementieren:
    • PdfDocument — Seine render() Methode gibt "PDF: $content" zurück.
    • HtmlDocument — Seine render() Methode gibt "<html>$content</html>" zurück.
    • TextDocument — Seine render() Methode gibt "TXT: $content" zurück.
  • DocumentFactory.php — Binden Sie die Datei Documents ein und erstellen Sie eine DocumentFactory Klasse mit einer statischen Methode create(string $type): Document. Diese Methode sollte match verwenden, um basierend auf dem Typ das entsprechende Dokumentobjekt zurückzugeben:
    • "pdf" gibt ein neues PdfDocument zurück.
    • "html" gibt ein neues HtmlDocument zurück.
    • "text" gibt ein neues TextDocument zurück.
    • Jeder andere Typ sollte eine InvalidArgumentException mit der Nachricht "Unknown document type: $type" werfen.
  • main.php — Binden Sie die Datei DocumentFactory ein. Sie erhalten zwei Eingaben: einen Dokumenttyp und den zu rendernden Inhalt.

    Verwenden Sie die Factory, um den entsprechenden Dokumenttyp zu erstellen, rufen Sie dann dessen render() Methode mit dem Inhalt auf und geben Sie das Ergebnis aus.

    Geben Sie in einer neuen Zeile "Factory benefit: Adding new types only requires updating the factory" aus, um hervorzuheben, warum dieses Pattern wertvoll ist.

Das Factory Pattern hält Ihren Code flexibel — wenn Sie später ein MarkdownDocument hinzufügen müssen, aktualisieren Sie nur die Factory, während der gesamte bestehende Code unverändert weiterfunktioniert.

Spickzettel

Das Factory Pattern delegiert die Objekterstellung an eine separate Klasse oder Methode, anstatt new direkt im gesamten Code zu verwenden.

Dieses Muster ist nützlich, wenn Sie mehrere verwandte Klassen haben, die eine gemeinsame Schnittstelle teilen, und Sie basierend auf einer Bedingung entscheiden müssen, welche davon instanziiert werden soll.

Beispiel mit einem Benachrichtigungssystem:

<?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";
    }
}

Die Factory zentralisiert die Logik zur Objekterstellung:

<?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!

Hauptvorteile:

  • Der Code hängt vom Interface ab, nicht von konkreten Klassen
  • Das Hinzufügen neuer Typen erfordert nur die Aktualisierung der Factory
  • Bestehender Code erhält automatisch Zugriff auf neue Typen, ohne dass Änderungen erforderlich sind

Probier es selbst

<?php
require_once 'DocumentFactory.php';

// Eingabe lesen
$type = trim(fgets(STDIN));
$content = trim(fgets(STDIN));

// TODO: DocumentFactory verwenden, um den entsprechenden Dokumenttyp zu erstellen
// TODO: Die render()-Methode mit dem Inhalt aufrufen und das Ergebnis ausgeben
// TODO: In einer neuen Zeile "Factory benefit: Adding new types only requires updating the factory" ausgeben

?>
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung