Singleton

Warum du kein Singleton benutzen solltest

Jeder angehende Entwickler kommt früher oder später an den Punkt, an denen er sich mit Entwurfsmustern auseinandersetzt. Entweder, weil ein anderer Entwickler ihm dazu rät, oder weil er ein Buch liest. Doch nicht alle Entwurfsmuster sind ohne Vorbehalte zu genießen. Wir klären, was ein Singleton ist, was seine Vorteile und Nachteile sind und fragen uns nach Sinnhaftigkeit und möglichen Alternativen.

Der Charakter eines Singletons

Das Singleton-Muster an sich ist sehr simpel und gehört als “creational pattern” zur Gang of four. Es soll sicherstellen, dass es nur eine Instanz einer Klasse gibt. Das kann zum Beispiel so aussehen:

1
2
3
4
5
6
7
8
9
10
11
12
13
public final class Singleton {
private static Singleton instance;

private Singleton() {
}

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

Vorteile eines Singletons

Singletons werden gerne genutzt, um weitere Instanziierungen zu verhindern. Als alternative zu einfach global sichtbaren Variablen lässt sich mit dem Singleton außerdem eine gewisse Zugriffskontrolle sicherstellen. Die Erzeugung nach Bedarf (“lazy”) kann außerdem Performance einsparen.
Außerdem werden Singletons gerne benutzt, wenn eine Implementierung erst zur Laufzeit fest steht und man diese Logik kapseln möchte. Im Endeffekt ist ein Singleton eine einfache Möglichkeit, einen globalen State zu verwalten. Aber ist das gut?

Nachteile eines Singletons

Bei der Entwicklung mit Singletons fällt sofort auf: Das ist fast unmöglich testbar! Es bedarf PowerMock oder ähnlichen Tools, um Singletons, oder Code der von ihnen abhängt testbar zu machen.
Singletons sind nämlich äußerst intransparent und verbergen eventuell Abhängigkeiten. Abhängigkeiten werden zu einem Implementierungsdetail und ich kann mich nicht auf die Schnittstelle verlassen.
Sie führen zu einer engen Kopplung zwischen Komponenten und provozieren häufig weitere Singletons.
Das Singleton, so wie es oben gezeigt wurde, ist außerdem nicht synchronisiert und es bedarf einigen mehr Zeilen, um dies umzusetzen.
Singletons verletzen das Single Responsibility Principle, indem sie sich selbst um ihren kompletten Lebenszyklus und ihre eigentliche Aufgabe kümmern.
Die von manchen geliebte Zugangskontrolle stellt sich sehr schnell auch als Flaschenhals heraus, wenn eine einzelne Instanz auf einmal gar nicht mehr zielführend ist. Das Refactoring gestaltet sich dann in der Regel sehr umständlich.

Fazit

Insgesamt lässt sich sagen, dass Singletons eigentlich eher ein Anti-Pattern sind. Wenngleich sie schnell entwickelt sind und in einer sehr kleinen Codebase sehr effizient sein können, führen sie auf Dauer zu schlechtem Stil, untestbarem Code und bösen Überraschungen.
Singletons sind dahingehend eigentlich ein Überbleibsel aus prozeduralem Code und haben mit Objektorientierung eigentlich nicht allzuviel zu tun. Singletons werden gerne oft weiter ineinander verschachtelt, wodurch zum Beispiel solche Code Schnipsel entstehen:

1
Application.getInstance().getModuleManager().getModule("myModule")

Sie laden geradeso dazu ein, das Gesetz von Demeter zu brechen und sind schlussendlich schlechter Stil und sollten vermieden werden.

Alternativen

Die eigentlich einzig wahre Alternative zu Singletons ist die Dependency Injection. Wenn ihr euch selbst einen Gefallen tun wollt, dann verabschiedet euch noch heute von Singletons und nutzt Dependency Injection. Für Java gibt es Tools wie Guice, die das sehr einfach und elegant ermöglichen.
Ich hoffe ich konnte einige Sünder bekehren, cheers!

Felix Klauke

Felix Klauke