5.1 Singleton Pattern
- Einzige Instanz: Genau ein Objekt wird erstellt.
- Globaler Zugriffspunkt: Dieses Objekt ist global zugänglich.
- Kontrollierter Zugriff: Die Klasse kontrolliert die Instanziierung selbst.
Es gibt mehrere bewährte Varianten, ein Singleton in Java zu implementieren:
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)
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.
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
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
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
In Java oft die bevorzugte Form: Die JVM garantiert eine Instanz, Serialisierung und Reflection sind unkritischer als bei den Varianten oben.
public enum Singleton {
INSTANCE;
public void doWork() {
// ...
}
}
Aufruf: Singleton.INSTANCE.doWork().
Das Singleton Pattern ist nützlich, wenn eine Klasse nur eine Instanz haben soll. In Java sind Enum-Singleton oder die statische Holder-Klasse in der Regel die klarsten threadsicheren Varianten. Double-Checked Locking bleibt eine Option, wenn ein Enum nicht passt. Die Wahl hängt von Initialisierungszeitpunkt und Serialisierung ab.