Während ich der Antwort von Andy Turner zustimme, Singletons zu vermeiden, wenn möglich, füge ich das der Vollständigkeit halber hinzu: Die statisch synchronisierte getInstance-Methode ist ein Relikt aus der Vergangenheit. Es gibt mindestens 3 Singleton-Musterimplementierungen, die dies nicht erfordern.
a) eifrig Singletons
public class EagerSingleton{
private EagerSingleton(){}
private static final EagerSingleton INSTANCE = new EagerSingleton();
public static EagerSingleton getInstance(){ return INSTANCE; }
}
Diese Klasse bei Lastzeit initialisiert wird, wann immer die Klasse EagerSingleton in irgendeiner Weise Referenz (beispielsweise durch eine Variable dieses Typs erklärt).
b) faul Singletons
public class LazySingleton{
private LazySingleton(){}
private static class Holder{
private static final LazySingleton INSTANCE = new LazySingleton();
}
public static LazySingleton getInstance(){ return Holder.INSTANCE; }
}
Diese bei Anrufzeit initialisiert wird, (das erste Mal, wenn Sie die Methode getInstance nennen). Der Klassenlader lädt jetzt die Halterklasse und initialisiert das Feld INSTANZ, und dies wird garantiert auf eine synchronisierte Art und Weise durchgeführt. Verwenden Sie diese Version, wenn Ihr Singleton teuer eingerichtet ist und nicht immer notwendig ist.
c) Enum Singleton
public enum EnumSingleton{
INSTANCE;
// and if you want, you can add the method, too, but it's
// unnecessary:
public static EnumSingleton getInstance(){ return INSTANCE; }
}
Enum-Artikel sind Kompilierung-Konstanten, dh ihre Einzigartigkeit zur Compile-Zeit garantiert ist, nicht nur zur Laufzeit (zur Laufzeit, ist Singletons einzigartige pro Class Loader, und dass gilt für alle Versionen). Dies ist der beste Weg zu gehen, es sei denn, Ihre Anforderungen sind von einer bestehenden Klasse zu erweitern.
Die Enum-Version gibt Ihnen viele andere Funktionen kostenlos:
- gleich/hashCode/toString Implementierungen aus der Box
- Verteidigung gegen Deserialisierung Angriffe
- Multiton-Unterstützung (fügen Sie einfach einen weiteren Aufzählungs Artikel)
Also das nächste Mal, wenn Sie jemand die doppelt überprüft Verriegelung oder ähnliches schreiben sehen, ihnen sagt, sie sind viel zu kompliziert und Technik al. Lassen Sie den Klassenlader die Arbeit für Sie erledigen.
Mit allen 3 Versionen: Stellen Sie sicher, dass die von Ihnen verwendete Funktionalität durch eine Schnittstelle und Code für diese Schnittstelle und nicht den Implementierungstyp unterstützt wird. Dadurch wird Ihr Code testbar.
Im Idealfall würden Sie kein Singleton verwenden. Wenn es sein muss, verwende ich lieber eine 'enum', in diesem Fall würde ich' MySingleton.INSTANCE.doSomething() 'schreiben. –
Diese beiden Beispiele sind identisch, obwohl @PeterLawrey Recht hat, enums für Singletons zu empfehlen. –
Definieren Sie "richtig" - was genau fragen Sie? Es ist identisch anders als im ersten Beispiel, Sie erhalten die Instanz und verwenden sie später. –