Menu
Coddy logo textTech

Singleton-Muster

Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy. Lektion 65 von 87.

Das Singleton Pattern ist ein erzeugendes Entwurfsmuster, das sicherstellt, dass eine Klasse während der gesamten Anwendung nur eine Instanz hat, und gleichzeitig einen globalen Zugriffspunkt auf diese Instanz bereitstellt. Dies ist nützlich für Ressourcen, die gemeinsam genutzt werden sollten, wie etwa Konfigurationsmanager, Verbindungspools oder Protokollierungsdienste.

Das Muster funktioniert, indem der Konstruktor privat gemacht wird, wodurch eine direkte Instanziierung verhindert wird. Stattdessen steuert eine statische Methode den Zugriff auf die einzige Instanz:

public class DatabaseConnection {
    private static DatabaseConnection instance;
    
    // Privater Konstruktor verhindert direkte Instanziierung
    private DatabaseConnection() {
        System.out.println("Connection created");
    }
    
    // Globaler Zugriffspunkt
    public static DatabaseConnection getInstance() {
        if (instance == null) {
            instance = new DatabaseConnection();
        }
        return instance;
    }
    
    public void query(String sql) {
        System.out.println("Executing: " + sql);
    }
}

Jeder Aufruf von getInstance() gibt dasselbe Objekt zurück. Die Instanz wird erst erstellt, wenn sie erstmals angefordert wird. Dies wird als verzögerte Initialisierung bezeichnet:

DatabaseConnection db1 = DatabaseConnection.getInstance();
DatabaseConnection db2 = DatabaseConnection.getInstance();

System.out.println(db1 == db2);  // true - same instance

Die wichtigsten Bestandteile eines Singleton sind: ein private static-Feld, das die Instanz enthält, ein private-Konstruktor und eine public static-Methode, die die Instanz zurückgibt. Diese Kombination garantiert, dass du unabhängig davon, wie oft du das Objekt anforderst, immer dasselbe erhältst.

challenge icon

Aufgabe

Einfach

Erstellen wir einen Konfigurationsmanager für eine Anwendung mithilfe des Singleton-Musters! Dein Konfigurationsmanager stellt sicher, dass alle Teile deiner Anwendung dieselben Einstellungen verwenden, unabhängig davon, wie oft sie darauf zugreifen.

Du wirst deinen Code auf zwei Dateien verteilen:

  • AppConfig.java: Erstelle eine Singleton-Klasse, die die Konfigurationseinstellungen der Anwendung verwaltet. Deine AppConfig sollte Folgendes enthalten:

    Ein privates statisches Feld, das die einzige Instanz speichert.

    Ein privates String-Feld namens appName und ein privates int-Feld namens maxUsers.

    Einen privaten Konstruktor, der appName auf "MyApplication" und maxUsers auf 100 setzt und anschließend AppConfig initialized ausgibt.

    Eine öffentliche statische Methode getInstance(), die die Instanz nur erstellt, wenn sie noch nicht existiert (verzögerte Initialisierung), und sie anschließend zurückgibt.

    Eine Methode setAppName(String name), die den Namen der Anwendung aktualisiert.

    Eine Methode setMaxUsers(int max), die die maximale Benutzeranzahl aktualisiert.

    Eine Methode displaySettings(), die App: [appName], Max Users: [maxUsers] ausgibt.

  • Main.java: Zeige, dass dein Singleton korrekt funktioniert! Du erhältst zwei Eingaben: einen neuen Anwendungsnamen (String) und einen neuen Wert für die maximale Benutzeranzahl (Ganzzahl).

    Rufe zuerst eine Instanz von AppConfig ab und speichere sie in einer Variable namens config1. Rufe displaySettings() auf, um die Standardwerte anzuzeigen.

    Aktualisiere dann die Einstellungen mithilfe deiner Eingabewerte, indem du setAppName und setMaxUsers für config1 aufrufst.

    Rufe eine weitere Instanz ab und speichere sie in config2. Rufe displaySettings() für config2 auf, um zu beweisen, dass sie die über config1 vorgenommenen Änderungen widerspiegelt.

    Gib schließlich aus, ob beide Referenzen auf dasselbe Objekt zeigen: Same instance: [true/false], indem du config1 == config2 vergleichst.

Du erhältst zwei Eingaben in dieser Reihenfolge: den neuen Anwendungsnamen (String) und den neuen Wert für die maximale Benutzeranzahl (Ganzzahl).

Diese Aufgabe veranschaulicht den zentralen Vorteil des Singleton-Musters: Unabhängig davon, wie oft du die Konfiguration anforderst, erhältst du immer dieselbe Instanz mit demselben gemeinsamen Zustand!

Probier es selbst

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Eingaben lesen
        String newAppName = scanner.nextLine();
        int newMaxUsers = scanner.nextInt();
        
        // TODO: Erste Instanz von AppConfig holen und in config1 speichern
        
        // TODO: displaySettings() auf config1 aufrufen, um Standardwerte anzuzeigen
        
        // TODO: Einstellungen mit setAppName und setMaxUsers auf config1 aktualisieren
        
        // TODO: Eine weitere Instanz holen und in config2 speichern
        
        // TODO: displaySettings() auf config2 aufrufen, um zu beweisen, dass Änderungen geteilt werden
        
        // TODO: Ausgeben, ob beide Referenzen auf dasselbe Objekt zeigen:
        // "Same instance: [true/false]" using config1 == config2
    }
}
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-Java-Compiler