Menu
Coddy logo textTech

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 instance

Das 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");
}
challenge icon

Aufgabe

Einfach

Erstellen 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 eine Config-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 oder null, 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 (verwende count() für das Ergebnis von getAll())
    • Gib "App name: [value]" aus, um die über die zweite Referenz abgerufene app_name-Einstellung anzuzeigen

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

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

Übe selbstständig: Online-PHP-Compiler