Wie lässt sich ein Singleton-Entwurfsmuster in Java effizient implementieren?
Antworten
Zu viele Anzeigen?Vergessen Sie verzögerte Initialisierung Das ist zu problematisch. Dies ist die einfachste Lösung:
public class A {
private static final A INSTANCE = new A();
private A() {}
public static A getInstance() {
return INSTANCE;
}
}
Vergewissern Sie sich, dass Sie es wirklich brauchen. Machen Sie eine Google-Suche nach "Singleton Anti-Pattern", um einige Argumente dagegen zu sehen.
Ich nehme an, dass daran an sich nichts falsch ist, aber es ist nur ein Mechanismus, um einige globale Ressourcen/Daten freizugeben, also stellen Sie sicher, dass dies der beste Weg ist. Insbesondere habe ich gefunden Dependency Injection (DI) nützlicher, insbesondere wenn Sie auch Unit-Tests verwenden, da DI die Verwendung von Mocked-Ressourcen zu Testzwecken ermöglicht.
Ich bin verblüfft über einige der Antworten, die nahelegen Dependency Injection (DI) als Alternative zur Verwendung von Singletons; es handelt sich dabei um zwei unterschiedliche Konzepte. Sie können DI verwenden, um entweder Singleton-Instanzen oder Nicht-Singleton-Instanzen (z. B. pro Thread) zu injizieren. Zumindest gilt dies, wenn Sie Spring 2.x verwenden, für andere DI-Frameworks kann ich nicht sprechen.
Meine Antwort auf die OP wäre also (in allen außer dem trivialsten Beispielcode) zu:
- Verwenden Sie ein DI-Framework wie Spring Framework dann
- Machen Sie es zu einem Teil Ihrer DI-Konfiguration, ob Ihre Abhängigkeiten singletons, request scoped, session scoped, oder was auch immer sind.
Mit diesem Ansatz erhalten Sie eine schöne entkoppelte (und daher flexible und testbare) Architektur, bei der die Verwendung eines Singletons ein leicht umkehrbares Implementierungsdetail ist (vorausgesetzt, alle Singletons, die Sie verwenden, sind natürlich threadsafe).
Überlegen Sie genau, warum Sie ein Singleton brauchen, bevor Sie es schreiben. Es gibt eine quasi-religiöse Debatte über die Verwendung von Singletons, über die Sie ganz einfach stolpern können, wenn Sie Singletons in Java googeln.
Ich persönlich versuche, Singletons so oft wie möglich zu vermeiden, und zwar aus vielen Gründen, von denen man die meisten wiederum durch Googeln von Singletons herausfinden kann. Ich habe das Gefühl, dass Singletons oft missbraucht werden, weil sie für jeden leicht zu verstehen sind. Sie werden als Mechanismus verwendet, um "globale" Daten in einen OO-Entwurf zu bekommen, und sie werden verwendet, weil es einfach ist, das Objektlebenszyklusmanagement zu umgehen (oder wirklich darüber nachzudenken, wie man A von B aus tun kann). Sehen Sie sich Dinge an wie Umkehrung der Steuerschuldnerschaft (IoC) oder Dependency Injection (DI) für einen guten Mittelweg.
Wenn Sie wirklich eine brauchen, dann hat Wikipedia ein gutes Beispiel für eine richtige Implementierung eines Singletons.
Im Folgenden werden drei verschiedene Ansätze vorgestellt
-
Enum
/** * Singleton pattern example using Java Enum */ public enum EasySingleton { INSTANCE; }
-
Doppelt geprüftes Sperren / träges Laden
/** * Singleton pattern example with Double checked Locking */ public class DoubleCheckedLockingSingleton { private static volatile DoubleCheckedLockingSingleton INSTANCE; private DoubleCheckedLockingSingleton() {} public static DoubleCheckedLockingSingleton getInstance() { if(INSTANCE == null) { synchronized(DoubleCheckedLockingSingleton.class) { // Double checking Singleton instance if(INSTANCE == null) { INSTANCE = new DoubleCheckedLockingSingleton(); } } } return INSTANCE; } }
-
Statische Fabrikmethode
/** * Singleton pattern example with static factory method */ public class Singleton { // Initialized during class loading private static final Singleton INSTANCE = new Singleton(); // To prevent creating another instance of 'Singleton' private Singleton() {} public static Singleton getSingleton() { return INSTANCE; } }