Singleton-Muster
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 71 von 91.
Das Singleton-Muster ist ein erzeugendes Entwurfsmuster, das sicherstellt, dass eine Klasse während des gesamten Lebenszyklus deiner Anwendung nur eine Instanz hat. Es stellt außerdem einen globalen Zugriffspunkt auf diese Instanz bereit.
Dieses Muster ist nützlich, wenn du genau ein Objekt benötigst, das Aktionen im gesamten System koordiniert, beispielsweise eine Datenbankverbindung, einen Konfigurationsmanager oder einen Logger. Das Erstellen mehrerer Instanzen davon würde Ressourcen verschwenden oder zu inkonsistentem Verhalten führen.
So implementierst du ein Singleton in PHP:
<?php
class Database {
private static ?Database $instance = null;
private function __construct() {
// Privater Konstruktor verhindert 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 wesentlichen Elementen: einem privaten Konstruktor, der verhindert, dass new direkt verwendet wird, einer statischen Eigenschaft, die die einzige Instanz enthält, und einer statischen Methode, die die Instanz beim ersten Aufruf erstellt und sie bei nachfolgenden Aufrufen zurückgibt.
Damit der Singleton wirklich kugelsicher ist, solltest du auch das Klonen und die Deserialisierung verhindern:
<?php
private function __clone() {}
public function __wakeup() {
throw new Exception("Cannot unserialize singleton");
}
Aufgabe
EinfachErstellen wir einen Konfigurationsmanager mit dem Singleton-Muster. In echten Anwendungen möchtest du normalerweise eine einzige Quelle der Wahrheit für Konfigurationseinstellungen haben: Mehrere Konfigurationsobjekte könnten zu inkonsistentem Verhalten in deinem System führen.
Du organisierst deinen Code auf zwei Dateien:
Config.php: Erstelle eineConfig-Klasse, die das Singleton-Muster implementiert. Dein 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()private 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 eines Schlüssels zurückgibt odernull, wenn der Schlüssel nicht existiert - Eine
getAll(): array-Methode enthalten, die alle Einstellungen zurückgibt
main.php: Binde die Config-Datei ein. Du erhältst zwei Eingaben: einen Schlüssel und einen Wert.Rufe die Config-Instanz ab und setze eine Standardeinstellung mit dem Schlüssel
"app_name"und dem Wert"MyApp".Rufe eine zweite Referenz auf die Config-Instanz ab (wieder mit
getInstance()) und verwende sie, um eine weitere Einstellung mit dem Schlüssel und dem Wert aus den Eingaben zu setzen.Überprüfe schließlich, ob das Singleton korrekt funktioniert:
- Gib
"Same instance: true"oder"Same instance: false"aus, je nachdem, ob beide Referenzen auf dasselbe Objekt zeigen (verwende zum Vergleichen===) - Gib
"Settings count: [count]"aus, um die Gesamtzahl der gespeicherten Einstellungen anzuzeigen (verwendecount()für das Ergebnis vongetAll()) - Gib
"App name: [value]"aus, um die über die zweite Referenz abgerufene app_name-Einstellung anzuzeigen
- Gib
Diese Herausforderung veranschaulicht den grundlegenden Vorteil des Singleton-Musters: Egal, wie oft du getInstance() aufrufst, du erhältst immer dasselbe Objekt. Dadurch stellen alle Teile deiner Anwendung denselben Konfigurationszustand gemeinsam bereit.
Probier es selbst
<?php
require_once 'Config.php';
// Eingabe lesen
$key = trim(fgets(STDIN));
$value = trim(fgets(STDIN));
// TODO: Hole die Config-Instanz und setze "app_name" auf "MyApp"
// TODO: Hole eine zweite Referenz auf Config erneut mit getInstance()
// TODO: Verwende die zweite Referenz, um die Einstellung mit $key und $value aus der Eingabe zu setzen
// TODO: Überprüfe, ob Singleton funktioniert:
// - Print "Same instance: true" or "Same instance: false" based on === comparison
// - Print "Settings count: [count]" showing total settings
// - Gib "App name: [value]" aus und zeige app_name, das über die zweite Referenz abgerufen wurde
?>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