Singleton-Muster
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 71 von 91.
Das Singleton-Muster ist ein Erzeugungsmuster, das sicherstellt, dass eine Klasse während des gesamten Lebenszyklus Ihrer Anwendung nur eine einzige Instanz hat. Es bietet zudem einen globalen Zugriffspunkt auf diese Instanz.
Dieses Muster ist nützlich, wenn Sie genau ein Objekt benötigen, um Aktionen im gesamten System zu koordinieren, wie zum Beispiel eine Datenbankverbindung, einen Konfigurationsmanager oder einen Logger. Das Erstellen mehrerer Instanzen davon würde Ressourcen verschwenden oder zu inkonsistentem Verhalten führen.
So implementieren Sie ein Singleton in PHP:
<?php
class Database {
private static ?Database $instance = null;
private function __construct() {
// Privater Konstruktor verhindert die direkte Instanziierung
}
public static function getInstance(): Database {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function query(string $sql): string {
return "Executing: $sql";
}
}
$db1 = Database::getInstance();
$db2 = Database::getInstance();
echo $db1 === $db2 ? "Same instance" : "Different instances";
Ausgabe:
Same instanceDas Muster beruht auf drei Schlüsselelementen: einem privaten Konstruktor, der die direkte Verwendung von new verhindert, einer statischen Eigenschaft, welche die einzige Instanz hält, und einer statischen Methode, die die Instanz beim ersten Aufruf erstellt und bei nachfolgenden Aufrufen zurückgibt.
Um das Singleton wirklich sicher zu machen, sollten Sie auch das Klonen und Deserialisieren verhindern:
<?php
private function __clone() {}
public function __wakeup() {
throw new Exception("Cannot unserialize singleton");
}
Aufgabe
EinfachLassen Sie uns einen Konfigurationsmanager mit dem Singleton-Pattern erstellen. In realen Anwendungen möchte man in der Regel eine einzige "Source of Truth" für Konfigurationseinstellungen haben — mehrere Konfigurationsobjekte könnten zu inkonsistentem Verhalten in Ihrem System führen.
Sie werden Ihren Code auf zwei Dateien aufteilen:
Config.php— Erstellen Sie eineConfig-Klasse, die das Singleton-Pattern implementiert. Ihr Konfigurationsmanager sollte:- Einstellungen in einer privaten Array-Eigenschaft speichern
- Einen privaten Konstruktor haben, der das Einstellungs-Array als leer initialisiert
- Eine statische
getInstance()-Methode bereitstellen, die die einzige Instanz zurückgibt - Das Klonen verhindern, indem
__clone()privat gemacht wird - Eine
set(string $key, string $value): void-Methode enthalten, um eine Einstellung zu speichern - Eine
get(string $key): ?string-Methode enthalten, die den Wert für einen Schlüssel zurückgibt, odernull, wenn der Schlüssel nicht existiert - Eine
getAll(): array-Methode enthalten, die alle Einstellungen zurückgibt
main.php— Binden Sie die Config-Datei ein. Sie erhalten zwei Eingaben: einen Schlüssel und einen Wert.Holen Sie sich die Config-Instanz und setzen Sie eine Standardeinstellung mit dem Schlüssel
"app_name"und dem Wert"MyApp".Holen Sie sich eine zweite Referenz auf die Config-Instanz (indem Sie erneut
getInstance()aufrufen) und verwenden Sie diese, um eine weitere Einstellung mit dem Schlüssel und dem Wert aus den Eingaben zu setzen.Überprüfen Sie schließlich, ob das Singleton korrekt funktioniert:
- Geben Sie
"Same instance: true"oder"Same instance: false"aus, je nachdem, ob beide Referenzen auf dasselbe Objekt zeigen (verwenden Sie===zum Vergleich) - Geben Sie
"Settings count: [count]"aus, um die Gesamtzahl der gespeicherten Einstellungen anzuzeigen (verwenden Siecount()auf das Ergebnis vongetAll()) - Geben Sie
"App name: [value]"aus, um die Einstellung app_name anzuzeigen, die über die zweite Referenz abgerufen wurde
- Geben Sie
Diese Herausforderung demonstriert den Kernvorteil des Singleton-Patterns: Egal wie oft Sie getInstance() aufrufen, Sie erhalten immer dasselbe Objekt, wodurch sichergestellt wird, dass alle Teile Ihrer Anwendung denselben Konfigurationszustand teilen.
Spickzettel
Das Singleton-Pattern stellt sicher, dass eine Klasse während des gesamten Lebenszyklus Ihrer Anwendung nur eine einzige Instanz hat, und bietet einen globalen Zugriffspunkt auf diese Instanz.
Dieses Muster ist nützlich für Objekte wie Datenbankverbindungen, Konfigurationsmanager oder Logger, bei denen mehrere Instanzen Ressourcen verschwenden oder inkonsistentes Verhalten verursachen würden.
Grundlegende Singleton-Implementierung:
<?php
class Database {
private static ?Database $instance = null;
private function __construct() {
// Private constructor prevents direct instantiation
}
public static function getInstance(): Database {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}
$db1 = Database::getInstance();
$db2 = Database::getInstance();
echo $db1 === $db2 ? "Same instance" : "Different instances";
// Output: Same instance
Kernelemente:
- Privater Konstruktor — verhindert die direkte Verwendung von
new - Statische Eigenschaft — hält die einzelne Instanz
- Statische Methode — erstellt die Instanz beim ersten Aufruf und gibt sie bei nachfolgenden Aufrufen zurück
Verhindern von Klonen und Deserialisierung:
<?php
private function __clone() {}
public function __wakeup() {
throw new Exception("Cannot unserialize singleton");
}
Probier es selbst
<?php
require_once 'Config.php';
// Eingabe lesen
$key = trim(fgets(STDIN));
$value = trim(fgets(STDIN));
// TODO: Die Config-Instanz abrufen und "app_name" auf "MyApp" setzen
// TODO: Eine zweite Referenz auf Config mit getInstance() erneut abrufen
// TODO: Die zweite Referenz verwenden, um die Einstellung mit $key und $value aus der Eingabe zu setzen
// TODO: Überprüfen, ob Singleton funktioniert:
// - "Same instance: true" oder "Same instance: false" basierend auf dem === Vergleich ausgeben
// - "Settings count: [count]" mit der Gesamtzahl der Einstellungen ausgeben
// - "App name: [value]" mit dem über die zweite Referenz abgerufenen app_name ausgeben
?>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 die OOPKlassen vs. ObjekteDas $this-SchlüsselwortMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick - Einfacher Taschenrechner4Vererbung
Grundlagen der VererbungDas parent:: SchlüsselwortMethoden überschreibenDas final SchlüsselwortAbstrakte KlassenZusammenfassung – Mitarbeiter-Hierarchie7Kapselung
Public, Protected, PrivateZugriffsmodifikatoren im DetailGetter und SetterInformation HidingConstructor Promotion (8.0)Zusammenfassung – Studentenverwaltungssystem2Namensräume & Autoloading
Einführung in NamensräumeDas use-SchlüsselwortPSR-4 Autoloading-StandardComposer AutoloaderZusammenfassung – Organisiertes Projekt5Interfaces & Verträge
Einführung in InterfacesInterfaces implementierenMehrfache Interface-ImplementierungInterface vs. Abstrakte KlasseType Hinting mit InterfacesZusammenfassung – Formen-Rechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objekt-Klonen__serialize & __unserializeZusammenfassung - Eigene Collection11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenEigene Exception-HierarchieTry, Catch, FinallyZusammenfassung - Formular-Validator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klasseneigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenReadonly-Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphismus
Method Overriding erneut betrachtetPolymorphismus über InterfacesType Hinting & Union TypesLate Static BindingZusammenfassung – Payment Processor9Traits
Einführung in TraitsVerwendung mehrerer TraitsKonfliktlösung bei TraitsAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung