Dies ist eine Liste von Implementierungen des Entwurfsmusters Singleton in unterschiedlichen Programmiersprachen.

Implementierung in ActionScript Ab Version 2 (ohne Schutz vor direkter Instanziierung) class Singleton { private static var _instance:SingletonClass;

private function Singleton() {

public static function get instance():Singleton { if(!_instance) _instance = new Singleton(); return _instance;

public function doSomething():Void {

/* @use: Singleton.instance.doSomething(); */

Ab Version 3 In ActionScript 3 können Konstruktoren nicht als privat deklariert werden. Eine mögliche Lösung besteht darin, mittels einer privaten Klasse sicherzustellen, dass der Konstruktor nur von innerhalb der Singletonklasse aufgerufen werden kann:

package { public class Singleton {

private static var _instance:Singleton = null;

public function Singleton(se:SingletonEnforcer) { if(se === null) { throw new Error('Singleton kann nicht direkt erstellt werden. Verwende Singleton.instance');

public static function get instance():Singleton { if(_instance === null) { _instance = new Singleton(new SingletonEnforcer() );

return _instance;

internal class SingletonEnforcer {}

Implementierung in C# Allgemein ohne Threadsicherheit // Nur zur Veranschaulichung – bitte nicht verwenden! class Singleton

private Singleton() { } private static Singleton instance = null;

public static Singleton Instance

get

if (instance == null)

instance = new Singleton();

return instance;

Verwendung:

Singleton a = Singleton.Instance; Singleton b = Singleton.Instance;

Assert.AreEqual(a,b);

Threadsicher Eine threadsichere Methode, entnommen aus dem MSDN-Magazin. class Singleton { private Singleton() { /* ...hier optional Initialisierungscode... */ } public static readonly Singleton Instance = new Singleton(); }

Verwendung:

Singleton a = Singleton.Instance; Singleton b = Singleton.Instance;

Assert.AreEqual(a,b);

Das Singleton-Prinzip wird bei C# durch zwei Maßnahmen erreicht: Durch die Deklaration des Konstruktors als privat (private Singleton(){}) kann dieser von außerhalb der Klasse nicht mehr aufgerufen werden – das Erstellen des Objektes ist also nur noch von innerhalb der Klasse möglich. Das statische öffentliche Feld Instance speichert und liefert schreibgeschützt Zugriff auf das einzige Objekt der Klasse.

Wichtig Der Konstruktor wird von der CLR nicht automatisch beim Programmstart aufgerufen. Erst beim ersten Zugriff auf eine Klasse werden alle statischen Member der Klasse initialisiert – in diesem Fall die Instanziierung des einen Objektes. Wenn also nie auf diese Klasse zugegriffen wird, wird der Konstruktor auch niemals ausgeführt – und das Objekt wird nie erstellt. Dieser Effekt tritt auch dann noch ein, wenn die Klasse selbst als statisch deklariert wird.

Möchte man sichergehen, dass das Singleton-Objekt beim Programmstart erstellt wird, so muss man einen beliebigen Zugriff in das Hauptprogramm (public static void Main() { }) einbauen.

Threadsicher mit doppelt überprüfter Sperrung Bei der doppelt überprüften Sperrung handelt es sich um ein Antimuster. Jedoch funktioniert diese Variante threadsicher und wird oft von unerfahrenen Entwicklern eingesetzt. class Singleton { private Singleton() { } private static volatile Singleton instance;

public static Singleton Instance

get

// DoubleLock if (instance == null)

lock(_lock)

if (instance == null) instance = new Singleton();

return instance;

// Hilfsfeld für eine sichere Threadsynchronisierung private static object _lock = new object(); }

Verwendung:

Singleton a = Singleton.Instance; Singleton b = Singleton.Instance;

Assert.AreEqual(a,b);

Hinweise zum Code: Das private Hilfsobjekt _lock ist hier unbedingt notwendig. Die frühere gängige Methode lock(this){ … } hat sich als unzureichend herausgestellt, weil fehlerhafter oder böswilliger Code durch den Aufruf Monitor.Exit(Singleton); die Threadsicherheit einfach aushebeln kann. Double-Lock-Muster: Damit nach der Instanziierung des Objektes die bremsende Synchronisation per lock() wegfällt, wird dieselbe If-Abfrage zusätzlich vor dem Lock-Abschnitt eingesetzt. Das Schlüsselwort volatile bewirkt, dass die Instanz von mehreren Threads gleichzeitig bearbeitet werden kann.

Falls es keine konkreten Einwände gibt, dass das Singleton-Objekt auch schon früher instanziiert werden darf, ist der vorher beschriebene Code einfacher und schneller und daher in C# vorzuziehen.

Threadsicher mit Synchronisation Eine Umgehung des Double-Lock-Antimusters ist die Verwendung des MethodImpl-Attributs um einen synchronisierten Methodenaufruf zu gewährleisten. Dies entspricht dem Schlüsselwort synchronized in Java. class Singleton { private Singleton() { } private static volatile Singleton instance;

public static Singleton Instance

[MethodImpl(MethodImplOptions.Synchronized)] get

if (instance == null) instance = new Singleton(); return instance;

Verwendung:

Singleton a = Singleton.Instance; Singleton b = Singleton.Instance;

Assert.AreEqual(a,b);

Generisch Eine einfache generische Variante public class Singleton<T> where T : class, new() { private Singleton() { }

private class SingletonCreator

static SingletonCreator() { } internal static readonly T instance = new T();

public static T Instance

get

return SingletonCreator.instance;

Bei dieser Variante kann das Delegat-Konstruktor-Handshake-Pattern eingesetzt werden um sicherzustellen, dass der öffentliche parameterfreie Konstruktor nur von der generischen Singleton-Klasse aufgerufen werden kann:

public class SomeSingleton { public SomeSingleton(Singleton<SomeSingleton> caller)

if (caller == null)

throw new Exception();

Alternativ kann System.Reflection oder System.Diagnostics verwendet werden um Informationen über die aufrufende Objekt zu erhalten. Hierzu muss das aufzurufende Objekt im Konstruktor übergeben und analysiert werden. Zudem wird dabei nicht die new()-Bedingung erfüllt, weshalb das entsprechende Konstrukt entfernt werden muss.

Generisch mit statischer Fabrikmethode Bei dieser Variante wird eine statische Fabrikmethode verwendet, um die Singleton-Instanz zu erzeugen.

public class Singleton<T> where T : class { // Methode zur Erzeugung einer neuen Instanz, welche als Delegat übergeben wird public delegate T CreateInstanceDelegate(Singleton<T> caller); private static CreateInstanceDelegate CreateInstanceMethod { get; set; }

// Konstruktor public Singleton(CreateInstanceDelegate createInstanceMethod)

if (CreateInstanceMethod == null) throw new ArgumentNullException(); CreateInstanceMethod = createInstanceMethod;

// Lock-Objekt für Threadsicherheit static readonly object Padlock = new Object();

// Singleton-Instanz private static T _instance = null; public T Instance

get

lock (Padlock)

if (_instance == null) _instance = CreateInstanceMethod(this); return _instance;

Einsatz:

public sealed class SomeSingleton { public static SomeSingleton CreateInstance(Singleton<SomeSingleton> caller)

return (caller == null) ? null : new SomeSingleton();

private SomeSingleton() { } } Verwendung: SomeSingleton a = new Singleton<SomeSingleton>(SomeSingleton.CreateInstance).Instance; SomeSingleton b = new Singleton<SomeSingleton>(SomeSingleton.CreateInstance).Instance;

Assert.AreEqual(a,b);

Generisch, Abstrakt public abstract class Singleton<T> where T : Singleton<T> { private static T _instance; protected static bool IsInitialised { get { return (_instance != null); } }

protected static T Instance { get { (IsInitialised) ? SingletonCreator.Instance : null; } }

protected Singleton() { }

protected static void Init(T newInstance)

if (newInstance == null) throw new ArgumentNullException(); _instance = newInstance;

// da C# keine abstrakten statischen Methoden erlaubt, // wird die Erzeugung der Singleton-Instanz an diese Klasse weitergeleitet private class SingletonCreator

static SingletonCreator() { } internal static readonly T Instance = _instance;

Einsatz:

public sealed class SomeSingleton : Singleton<SomeSingleton> { public static SomeSingleton Instance

get

(IsInitialised) ? return UniqueInstance : Init(new SomeGenericSingleton());

private SomeSingleton() { } }

Verwendung: SomeSingleton a = SomeSingleton.Instance; SomeSingleton b = SomeSingleton.Instance;

Assert.AreEqual(a,b);

Generisch, Abstrakt, Lazy Dies ist eine generische abstrakte Klasse die eine Singleton-Instanz lazy erzeugt. public abstract class Singleton<T> where T : class { // Lazy Instanziierung private static readonly Lazy<T> _instance = new Lazy<T>( () => CreateSingletonInstance() );

public static T Instance

get

return _instance.Value;

private static T CreateSingletonInstance()

// Konstruktion des Singleton-Objekts return Activator.CreateInstance(typeof(T), true) as T;

Einsatz:

class SomeSingleton : Singleton<SomeSingleton> { // öffentliche Felder und Methoden public string SomeString {get; set; }

// Konstruktor muss private sein private SomeSingleton()

Verwendung:

SomeSingleton a = SomeSingleton.Instance; SomeSingleton b = SomeSingleton.Instance;

Assert.AreEqual(a,b);

Generisch mit Aufruf eines privaten Konstruktors über Reflexion Die folgende Variante ruft einen privaten Konstruktor über Reflexion auf: public class Singleton<T> where T : class { private Singleton() { }

private class SingletonCreator

static SingletonCreator() { Instance = CreateInstance(); }

private static T CreateInstance()

ConstructorInfo constructorInfo = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, Type.DefaultBinder, Type.EmptyTypes, null);

if (constructorInfo != null) return constructorInfo.Invoke(null) as T; else return null; // oder: throw new InvalidOperationException("Should have a private parameterless constructor");

internal static readonly T Instance { get; private set; }

public static T Instance

get { return SingletonCreator.Instance; }

Einsatz:

public class SomeSingleton : Singleton<SomeSingleton> { private SomeSingleton() { } }

Verwendung:

SomeSingleton a = SomeSingleton.Instance; SomeSingleton b = SomeSingleton.Instance;

Assert.AreEqual(a,b);

Implementierung in C++ Die Implementierung im Buch Entwurfsmuster ist nur für Single-Thread Programme geeignet. Bei Multi-Thread Programmen muss die get Methode durch ein Mutex geschützt werden. Diese C++11 Single-Thread Implementierung basiert auf der vor C++98 Implementierung im Buch Entwurfsmuster.

#include <iostream>

class Singleton { public: // definiert eine Klassenoperation, die es Klienten ermöglicht, auf sein einziges Exemplar (Instanz) zuzugreifen. static Singleton& get() { // ist potentiell für die Erzeugung seines einzigen Exemplars zuständig. if (nullptr == instance) instance = new Singleton; return *instance;

Singleton(const Singleton&) = delete; // Dreierregel Singleton& operator=(const Singleton&) = delete; static void destruct() { delete instance; instance = nullptr;

// existierende Schnittstelle folgt hier int getWert() { return wert;

void setWert(int wert_) { wert = wert_;

private: Singleton() = default; // kein public Konstruktor ~Singleton() = default; // kein public Dekonstruktor static Singleton* instance; // Deklaration Klassenvariable int wert;

Singleton* Singleton::instance = nullptr; // Definition Klassenvariable

int main() { Singleton::get().setWert(42); std::cout << "wert=" << Singleton::get().getWert() << '\n'; Singleton::destruct(); }

Die Programmausgabe ist:

wert=42

Das Meyers Singleton nutzt eine statische Variable in der Methode get. Deshalb gibt es keine destruct Methode. Die Programmausgabe ist wie oben.

#include <iostream>

class Singleton { public: static Singleton& get() { static Singleton instance; return instance;

int getWert() { return wert;

void setWert(int wert_) { wert = wert_;

private: Singleton() = default; ~Singleton() = default; int wert;