Skip to main content
Entwickler Themen
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

5.1 Singleton Pattern

Eigenschaften

  • Einzige Instanz: Genau ein Objekt wird erstellt.
  • Globaler Zugriffspunkt: Dieses Objekt ist global zugänglich.
  • Kontrollierter Zugriff: Die Klasse kontrolliert die Instanziierung selbst.

Typische Java-Implementierungen

Es gibt mehrere bewährte Varianten, ein Singleton in Java zu implementieren:

1. Eager Initialization

Die einfachste Form ist die direkte Instanziierung beim Laden der Klasse.

public class Singleton {
    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return INSTANCE;
    }
}

Vorteile:

  • Einfach
  • Threadsicher ohne Synchronisation

Nachteile:

  • Keine Lazy Initialization (Instanz wird immer erzeugt, selbst wenn nicht benutzt)

2. Lazy Initialization (nicht threadsicher)

Instanziierung erfolgt erst beim ersten Zugriff.

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

Achtung: Nicht threadsicher! Kann zu mehrfachen Instanzen führen.

3. Synchronized Lazy Initialization (threadsicher)

Durch Synchronisierung wird die Threadsicherheit gewährleistet.

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

Vorteile:

  • Threadsicher

Nachteile:

  • Performance-Einbußen durch Synchronisation bei jedem Zugriff

4. Double-Checked Locking (threadsicher, effizient)

Threadsichere Lazy Initialization mit verbesserter Performance.

public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

Wichtig: volatile stellt sicher, dass Änderungen an der Instanz sofort für alle Threads sichtbar sind.

Vorteile:

  • Threadsicher
  • Effizient durch reduzierte Synchronisation

5. Statische Holder-Klasse (Initialization-on-demand holder idiom)

Von JVM unterstützte Lazy-Initialization-Variante.

public class Singleton {
    private Singleton() {}

    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}

Vorteile:

  • Threadsicher
  • Lazy-Initialization garantiert durch JVM
  • Einfach und effizient

Fazit

Das Singleton Pattern ist nützlich, wenn eine Klasse nur eine einzige Instanz haben soll. Für Java-Anwendungen wird die statische Holder-Implementierung (Initialization-on-demand holder idiom) oder die Double-Checked Locking-Variante bevorzugt, da sie effizient, lazy und threadsicher sind.

Wähle stets die Implementierung, die am besten zu den Anforderungen deiner Anwendung passt.