Erzeugungsmuster: Factory, Builder, Singleton
Steuern Sie die Objekterzeugung sauber mit Erzeugungsmustern.
Erzeugungsmuster: Factory, Builder, Singleton ist eine kostenlose PHP Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des PHP Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der PHP Academy-Kurs umfasst insgesamt 4 Lektionen.
Steuern der Erstellung
Erzeugungsmuster entkoppeln das Benötigte davon, wie es erstellt wird. Wenn die Erstellung von Bedingungen abhängt, mehrere Schritte umfasst oder zentral erfolgen muss, koppelt ein im gesamten Code verstreutes new die Aufrufer an konkrete Klassen. Hier behandeln wir Factory (und Factory Method), Builder für den Zusammenbau komplexer Objekte sowie Singleton (mit seinen Einschränkungen).
Einfache Factory
Eine einfache Factory zentralisiert eine Erstellungsentscheidung hinter einer einzigen Methode. Aufrufer fragen nach einem logischen Typ und erhalten eine konfigurierte konkrete Instanz, ohne die Klassennamen kennen zu müssen.
<?php
interface Notifier { public function send(string $msg): string; }
final class EmailNotifier implements Notifier {
public function send(string $m): string { return "email: $m"; }
}
final class SmsNotifier implements Notifier {
public function send(string $m): string { return "sms: $m"; }
}
final class NotifierFactory {
public static function make(string $channel): Notifier {
return match ($channel) {
'email' => new EmailNotifier(),
'sms' => new SmsNotifier(),
default => throw new InvalidArgumentException($channel),
};
}
}
echo NotifierFactory::make('sms')->send('Hi'), PHP_EOL;
Factory Method
Das Muster Factory Method verlagert die Instanziierung in Unterklassen. Die Basisklasse definiert einen Algorithmus, der create() aufruft; jede Unterklasse entscheidet über das konkrete Produkt. Das unterstützt das OCP: Sie können einen neuen Ersteller hinzufügen, ohne bestehende zu ändern.
<?php
abstract class ReportExporter {
abstract protected function create(): string;
public function export(): string {
return 'Exported as ' . $this->create();
}
}
final class PdfExporter extends ReportExporter {
protected function create(): string { return 'PDF'; }
}
final class CsvExporter extends ReportExporter {
protected function create(): string { return 'CSV'; }
}
echo (new PdfExporter())->export(), PHP_EOL;
echo (new CsvExporter())->export(), PHP_EOL;
Abstract Factory
Eine Abstract Factory erzeugt Familien zusammengehöriger Objekte, die gemeinsam verwendet werden müssen (z. B. eine Kombination aus MySqlConnection und MySqlQueryBuilder). Sie garantiert die Kompatibilität der Bestandteile, weil eine Factory das gesamte Set liefert. Verwenden Sie sie, wenn eine Produktfamilie intern konsistent bleiben muss.
Builder: das Problem
Wenn ein Objekt viele optionale Parameter benötigt, führen Konstruktoren zu unlesbaren Listen positionsabhängiger Argumente oder zu einer Kaskade von Überladungen, die es in PHP nicht einmal gibt. Das Muster Builder setzt ein komplexes Objekt Schritt für Schritt zusammen und liefert am Ende ein fertiges, gültiges Produkt zurück.
Fluent Builder
Ein Fluent Builder gibt aus jedem Setter $this zurück; anschließend erzeugt build() das unveränderliche Ergebnis. Dadurch bleibt das Produkt selbst einfach, während die Logik für den Zusammenbau in den Builder verlagert wird.
<?php
final class Query {
public function __construct(public readonly string $sql) {}
}
final class QueryBuilder {
private string $table = '';
private array $where = [];
public function from(string $t): self { $this->table = $t; return $this; }
public function where(string $c): self { $this->where[] = $c; return $this; }
public function build(): Query {
$sql = "SELECT * FROM {$this->table}";
if ($this->where) { $sql .= ' WHERE ' . implode(' AND ', $this->where); }
return new Query($sql);
}
}
echo (new QueryBuilder())->from('users')->where('age > 18')->build()->sql, PHP_EOL;
Builder oder benannte Konstruktoren
Für einfachere Fälle sind benannte Argumente in PHP 8 und benannte Konstruktoren (statische Factory-Methoden) oft die bessere Wahl als ein vollständiger Builder.
- Verwenden Sie benannte Argumente, wenn alle Daten gleichzeitig verfügbar sind.
- Verwenden Sie einen Builder, wenn der Zusammenbau mehrere Schritte umfasst, von Bedingungen abhängt oder an mehreren Aufrufstellen wiederverwendet wird.
<?php
final class Money {
private function __construct(public readonly int $cents, public readonly string $cur) {}
public static function fromDollars(float $d): self {
return new self((int) round($d * 100), 'USD');
}
public static function zero(string $cur = 'USD'): self {
return new self(0, $cur);
}
}
var_dump(Money::fromDollars(19.99)->cents); // int(1999)
Singleton
Ein Singleton garantiert eine einzige Instanz mit einem globalen Zugriffspunkt. Implementieren Sie es mit einem privaten Konstruktor und einem statischen Zugriff. Es ist tatsächlich für Dinge sinnvoll, die innerhalb eines Prozesses wirklich eindeutig sein müssen, wird aber auch am häufigsten missbraucht.
<?php
final class Config {
private static ?self $instance = null;
private array $data = ['debug' => true];
private function __construct() {}
public static function instance(): self {
return self::$instance ??= new self();
}
public function get(string $k): mixed { return $this->data[$k] ?? null; }
}
var_dump(Config::instance()->get('debug'));
var_dump(Config::instance() === Config::instance()); // true
Warum Singleton problematisch ist
Singletons führen zu verdecktem globalem Zustand: Aufrufer greifen auf Config::instance() zu, anstatt die Abhängigkeit zu deklarieren. Das beeinträchtigt Testbarkeit und Parallelität. Verwenden Sie in modernem PHP stattdessen eine einzelne gemeinsam genutzte Instanz in einem DI-Container (Lebenszyklus „eine Instanz“) und injizieren Sie sie. So erhalten Sie eine Instanz ohne globale Kopplung.
Das richtige Werkzeug auswählen
- Simple/Factory Method: konkrete Klassen hinter einer Erstellungsentscheidung verbergen.
- Abstract Factory: kompatible Produktfamilien erzeugen.
- Builder: komplexe Objekte Schritt für Schritt zusammensetzen.
- Singleton: letzter Ausweg; bevorzugen Sie vom Container verwaltete gemeinsam genutzte Dienste.
Alle vier reduzieren die Kopplung an konkrete Konstruktoren und machen den Code leichter erweiterbar und testbar.
Registry-basierte Factory
Eine dynamischere Factory sucht Ersteller in einer Registry nach, sodass neue Typen sich selbst registrieren können, ohne die Factory zu ändern (echte OCP-Konformität). So lösen Pluginsysteme und Serializer zur Laufzeit einen Typnamen in einen Konstruktor auf.
<?php
interface Shape { public function name(): string; }
final class Circle implements Shape { public function name(): string { return 'circle'; } }
final class Square implements Shape { public function name(): string { return 'square'; } }
final class ShapeRegistry {
private array $creators = [];
public function register(string $key, callable $factory): void {
$this->creators[$key] = $factory;
}
public function create(string $key): Shape {
return ($this->creators[$key] ?? throw new InvalidArgumentException($key))();
}
}
$r = new ShapeRegistry();
$r->register('circle', fn() => new Circle());
$r->register('square', fn() => new Square());
echo $r->create('square')->name(), PHP_EOL; // square
Schnelltest
Wählen Sie für das Szenario das passende Erzeugungswerkzeug aus.
Zusammenfassung
Sie haben die Objekterstellung mit Erzeugungsmustern gesteuert: Factories verbergen konkrete Typen und wählen Produktfamilien aus, Builder setzen komplexe Objekte fluent zusammen, und Singleton bietet bestimmte Vorteile, hat aber auch Nachteile. Die moderne Schlussfolgerung: Verwenden Sie Factories und Builder unbeschwert, ersetzen Sie Singleton jedoch durch den Lebenszyklus einer gemeinsam genutzten Instanz in einem DI-Container, damit Abhängigkeiten explizit und testbar bleiben.
Häufig gestellte Fragen
Ist die Lektion „Erzeugungsmuster: Factory, Builder, Singleton“ kostenlos?
Ja — der vollständige Text von „Erzeugungsmuster: Factory, Builder, Singleton“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des PHP Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der PHP Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Erzeugungsmuster: Factory, Builder, Singleton“?
Steuern Sie die Objekterzeugung sauber mit Erzeugungsmustern. Du übst PHP Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um PHP Academy zu starten?
Keine Vorkenntnisse erforderlich. PHP Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.
Wie lange dauert die Lektion „Erzeugungsmuster: Factory, Builder, Singleton“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser PHP Academy-Lektion Code schreiben und ausführen?
Ja. Jede PHP Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- SOLID-Prinzipien in der Praxis
- Erzeugungsmuster: Factory, Builder, Singleton
- Strukturelle Muster: Adapter, Decorator, Facade
- Verhaltensmuster: Strategy, Observer, Command