Was sind Entwurfsmuster und warum werden sie in PHP benötigt?
Entwurfsmuster (design patterns) sind bewährte Lösungen für typische Aufgaben, die bei der Entwicklung von Software auftreten. Sie sind kein fertiger Code, sondern stellen Vorlagen dar, die an die jeweilige Situation angepasst werden können. Für einen PHP-Entwickler hilft die Kenntnis von Mustern dabei, flexibleren, wartbareren und skalierbareren Code zu schreiben.
In diesem Artikel betrachten wir vier grundlegende Muster aus dem GoF-Katalog (Gang of Four), die am häufigsten in realen PHP-Projekten verwendet werden. Jedes Muster wird von einem praktischen Beispiel und Erläuterungen begleitet.
1. Singleton (Einzelstück)
Das Singleton-Muster stellt sicher, dass von einer Klasse nur eine einzige Instanz existiert, und bietet einen globalen Zugriffspunkt darauf. Dies ist nützlich für die Verwaltung von Datenbankverbindungen, Loggern oder Caches.
Wann anwenden?
- Es wird genau ein Objekt benötigt (z. B. eine Datenbankverbindung).
- Das Objekt wird in der gesamten Anwendung verwendet, und die Erstellung von Duplikaten ist nicht zulässig.
Implementierungsbeispiel:
<?phpclass DatabaseConnection{ private static ?self $instance = null; private PDO $pdo;
private function __construct() { $this->pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'); }
public static function getInstance(): self { if (self::$instance === null) { self::$instance = new self(); } return self::$instance; }
public function getConnection(): PDO { return $this->pdo; }
// Klonen und Deserialisierung verbieten private function __clone() {} public function __wakeup() { throw new \\Exception("Cannot unserialize singleton"); }}
// Verwendung:$db = DatabaseConnection::getInstance();$pdo = $db->getConnection();?>Wichtig: Singleton wird oft kritisiert, weil es das Prinzip der einzigen Verantwortung verletzt und das Testen erschwert. Verwenden Sie es bewusst und nur dort, wo es wirklich notwendig ist.
2. Factory Method (Fabrikmethode)
Das Factory Method-Muster definiert eine Schnittstelle zur Erstellung eines Objekts, ermöglicht es jedoch Unterklassen, den Typ des zu erstellenden Objekts zu ändern. Dies erlaubt es, die Logik der Objekterstellung an untergeordnete Klassen zu delegieren.
Wann anwenden?
- Es ist im Voraus nicht bekannt, welches Objekt genau erstellt werden muss.
- Man möchte die komplexe Logik der Objekterstellung vor dem Client verbergen.
Implementierungsbeispiel:
<?php// Schnittstelle für alle Benachrichtigungstypeninterface Notification{ public function send(string $message): void;}
// Konkrete Implementierungenclass EmailNotification implements Notification{ public function send(string $message): void { echo "Sende Email: {$message}"; }}
class SMSNotification implements Notification{ public function send(string $message): void { echo "Sende SMS: {$message}"; }}
// Abstrakter Erstellerabstract class NotificationFactory{ abstract public function createNotification(): Notification;
public function notify(string $message): void { $notification = $this->createNotification(); $notification->send($message); }}
// Konkrete Fabrikenclass EmailFactory extends NotificationFactory{ public function createNotification(): Notification { return new EmailNotification(); }}
class SMSFactory extends NotificationFactory{ public function createNotification(): Notification { return new SMSNotification(); }}
// Verwendung:$factory = new EmailFactory();$factory->notify("Ihre Bestellung wurde bestätigt!");
$factory = new SMSFactory();$factory->notify("Bestätigungscode: 1234");