Einführung in das Singleton Pattern

veröffentlicht am 28. Oktober 2010

Das Singleton ist ein Design Pattern und gehört zu der Gruppe der Creational Pattern. Das Pattern ist dazu geeignet, um sicherzustellen, dass ein Objekt nur ein einziges Mal in einem Programm instanziiert werden kann. Zudem kann man global darauf zugreifen. Java bietet verschiedene Möglichkeiten, um ein Singleton zu Implementieren.

Lazy Creation

Bei dieser Variante wird das Singleton-Objekt beim ersten Zugriff erzeugt. Das ist dann sinnvoll, wenn man ein speicherschonendes Programm schreiben möchte. Nachteil ist jedoch, dass jeder Zugriff auf das Objekt synchronisiert ist, wodurch sich gleichzeitig zugreifende Threads blockieren. Deshalb sind die folgenden Methoden dieser hier vorzuziehen.

public final class Singleton {

   private static Singleton instance;

   private Singleton() {}

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

Eager Creation

Bei der so genannten Eager Creation wird das Objekt bereits bei der Initialisierung, also beim ersten Referenzieren des Objektes instantiiert.

public final class Singleton {

   private static final Singleton INSTANCE = new Singleton();

   private Singleton() {}

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

Initialization on demand holder idiom

Diese dritte Variante ist quasi eine Mischung aus der Lazy und der Eager Creation. Die Instanziierung des Singleton findet hier erst beim ersten Zugriff auf die getInstance()-Methode statt, da die Instanz in einer inneren Klasse erzeugt wird.

public final class Singleton {

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

   private Singleton() {}

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

Singleton per enum

Ab Java 5 werden auch enums unterstützt. Ein enum kann man deshalb auch dazu missbrauchen, um ein Singleton zu kreieren. Nachteil dieser Variante ist, dass man keine Klassen hiervon ableiten kann.

public enum Singleton {
   INSTANCE;
}

Schlussbemerkung

Singletons sind nicht ganz unumstritten in der modernen Softwareentwicklung. Dennoch ist es eine komfortable Möglichkeit, um sicherzugehen, dass nur eine Instanz einer Klasse erzeugt werden kann. Vor dem Einsatz eines Singleton sollte man sind ganz genau überlegen, ob das Problem nicht doch irgendwie anders gelöst werden kann.

Frage an euch: Falls sich überhaupt ein paar Java-Entwickler unter uns befinden (bitte melden :)), möchtet ihr zur Benutzung der Singletons noch Beispiele haben, oder reichen euch diese Codeschnipsel aus? Wie seht ihr die Verwendung von Singletons an?

Kommentare

Wenn ich nur eine Instanz einer Klasse brauche, erstelle ich eben auch nur eine und gut ists.
Mit einem Dependency-Injection Framework ist das dann auch leicht zu handlen.

Das mit dem global zugreifen ist auch eher ein Problem als dass es ein Vorteil ist(bei dir hörte sich das so an).
Natürlich kommt es da auch wieder darauf an was die Singleton-Klasse genau darstellen soll, bei einer Logger-Klasse o.ä. ist das wohl noch okay.

Ansonsten bin ich klar für die enum-Variante, die Anderen haben einige Schwachstellen. Per Reflection oder Serialisierung ist es auch dort ohne Probleme möglich mehrere Objekte zu erstellen, um dies zu verhindern muss einiges getan werden (leider wird dies zu selten erwähnt und erklärt, wie man auch dies unterbinden kann).
Bei dem enum allerdings hat man diese Probleme nicht!

Ansonsten steht ja auch schon einiges in dem o.g. Link =)

…just my 2 cents :)

Kommentar #1 von Basti am 28. Oktober 2010


Nehmen wir mal den Logger: dort ist es von Vorteil, global drauf zugreifen zu können ;)

Kommentar #2 von Patrick am 28. Oktober 2010


Nicht unbedingt, mit IoC kann man das eleganter lösen und dann z.B. einfacher eine Loggerimplementierung zu Testzwecken austauschen.

Kommentar #3 von Fabian Ritzmann am 28. Oktober 2010


Singleton-Klassen sind manchmal echt angenehm. Ich verwende sie z.B. in PHP für den Zugriff auf Websiten-Einstellungen.

Kommentar #4 von Maxim am 28. Oktober 2010


Ich vermisse gelegentlich Java in den Vorlesungen. Momentan schauen wir uns andere Sprachen an und „programmieren“ mit einer allgemeinen Sprache. Gerechterweise muss man auch sagen das es sich um die Vorlesung Algorithmen handelt und in der Problemlösungen im Vordergrund stehen.

Java ist eine der schönsten Sprachen. Schade das Sun pleite ist und von Oracel übernommen wurde.

Kommentar #5 von Le Mag am 07. November 2010


Über Google bin ich auf diesen Satz gestoßen:

„Ab Java 5 werden auch enums unterstützt. Ein enum kann man deshalb auch dazu missbrauchen, um ein Singleton zu kreieren. Nachteil dieser Variante ist, dass man keine Klassen hiervon ableiten kann.“

Also das ist eigentlich ziemlicher Käse. Das hat nichts mit Missbrauchen zu tun, sondern ein Singleton über enum ist die beste Umsetzung von Singletons, die Java anbieten kann. Es ist typsicher und über Reflexions nicht auszuhebeln. Joshua Bloch (effecite Java) empfiehlt diese Umsetzung für Singletons sogar. Aber klar ist, dass Singletons in einer objektorientierten Programmierung nichts zu suchen haben sollten ;)

Kommentar #6 von Rudolf Schmidt am 02. November 2012


Und wie ich persönlich zu Singletnos stehe: Sie haben in einer objektorientierten Programmierung nichts zu suchen. Schon Misko Hevery warnt in seinen Vorträgen mehrfach vor Singletons, da sie beim Testen der Software zu extrem schwer zu entdeckenden Seiteneffekten führen können. Also an alle, Finger weg von Singletons! Und Finger weg von static methods ;)

Kommentar #7 von Rudolf Schmidt am 02. November 2012


Hallo Rudolf,

was Singletons angeht, bin ich vollkommen bei dir, aber was spricht deiner Meinung nach gegen statische Methoden?

Gruß
Patrick

Kommentar #8 von Patrick am 03. November 2012


Haha, irgendwie wusste ich, dass die Frage kommt. Statische Methoden sind zwar nicht so schlimm wie Singletons, aber sie sind nur dann testbar, wenn sie auf dem untersten level ausgeführt werden. Wenn statische Methoden anfangen andere statische Methoden auszuführen, kann das testen sehr schwierig werden. Das Testen von Objekten wird meistens ja durch das Einsetzen von Mockklassen erlaubt, und diese Mockklassen können statische Methoden nicht überführen. Und es ist ja oft so. Man erstellt eine statische Methode und irgendwann wird auf der Methode eine Methode die andere Methoden aufruft usw. Also solange eine statische Methode auf dem untersten Leven bleibt wie bei Math.max() oder so, solange ist alles ok, aber

1. ist das nicht objektorientiertes Programmieren
2. Bietet man anderen Entwicklern eine mögliche Fehlerquelle an, indem man statische Methoden auf eine höhere Abstraktionsebene führt, und man sollte möglichst unnötige Fehlerquellen vermeiden.

Eine Gegenfrage an dich Patrick,

was spricht denn gegen nicht statische Methoden? Auch wenn es soweitgehen sollte, dass sie so aussehen: new OperationClass().operation()?

Kommentar #9 von Rudolf Schmidt am 03. November 2012


Moin Rudolf,

auch da bin ich bei dir, es sollten nicht komplexe Dinge mit statischen Methoden abgehandelt werden. Aber für Utility-Klassen beispielsweise sind statische Methoden einfach sinnvoll (man denke z.B. an diverse Utility Klassen von Apache Commons). Auch kann es nicht Ziel sein, viele solcher (Utility-)Klassen per Dependency Injection einzubinden, das würde die Testbarkeit der abhängigen Klassen wiederum verschlechtern.

Kommentar #10 von Patrick am 04. November 2012


Hinterlasse einen Kommentar