Singleton (ontwerppatroon)
Singleton is een ontwerppatroon om het aantal objecten van een bepaalde klasse tot één te beperken. Met dit ontwerppatroon is het mogelijk om de toegang tot bepaalde systeembronnen altijd via één object te laten gaan.
Een toepassing van de singleton is bijvoorbeeld het maken van unieke identificatienummers binnen een programma. Om er altijd zeker van te zijn dat elk identificatienummer uniek is, is het handig om dit door één enkel object te laten genereren. Dit is dan een singleton.
Een singleton wordt gemaakt door een klasse te definiëren met een methode die een nieuw object aanmaakt als het nog niet bestaat en een bestaand object teruggeeft als er al wel een dergelijk object bestaat.
Inhoud |
Klassediagram [bewerken]
Keerzijde van Singleton [bewerken]
Singleton is een van de meer controversiële ontwerppatronen die er zijn. De reden hiervoor is dat Singleton eigenlijk tegengesteld is aan de principes van het object-georiënteerd programmeren. Met name is het zo dat Singletons een enkele, globale instantie van een klasse introduceren binnen een programma in plaats van meerdere instanties van een klasse aangemaakt daar waar de instanties nodig zijn. Dit doorbreekt het normale patroon van een object-georiënteerd ontwerp en kan in feite een stap terug richting zijn het imperatief programmeren.
Daarnaast is het in veel talen zo dat de Singleton geïmplementeerd moet worden op een manier die het moeilijk maakt (of zelfs verhindert) om via overerving aanpassingen te maken aan de Singleton-klasse. In het bovenstaande voorbeeld is de Singleton bijvoorbeeld uitgevoerd met behulp van statische methoden. In Java is het zeer moeilijk om via overerving het gedrag van een statische methode aan te passen, het doorboort de object-georiënteerde ontwerpprincipes.
Tenslotte is er nog de praktische kritiek dat bij verkeerd gebruik met een Singleton vaak heel makkelijk is om geheugenlekken in een programma te introduceren. Enerzijds kan dit veroorzaakt worden doordat een Singleton onnodig geheugen inneemt als hij niet gebruikt wordt maar wel bestaat (en niet opgeruimd kan worden), anderzijds kunnen er geheugenproblemen ontstaan in talen als C++ waarin een component hard een Singleton weg kan werpen die elders nog nodig is. Als variatie op deze problemen is het in gedistribueerde programma's zonder voorzorgsmaatregelen ook vaak mogelijk dat een Singleton niet een Singleton is, maar toch meerdere malen geïnstantieerd wordt.
Voorbeelden [bewerken]
Java [bewerken]
Een voorbeeld in Java:
public class Singleton { private static Singleton _instance = null; // Private constructor vervangt de standaard public constructor private Singleton () {} //gesynchroniseerde creator om multi-threading-problemen te voorkomen //nog een controle om te voorkomen dat er meer dan een object wordt geïnstantieerd private synchronized static void createInstance () { if (_instance == null) _instance = new Singleton (); } public static Singleton getInstance () { if (_instance == null) createInstance (); return _instance; } }
C# [bewerken]
Een voorbeeld in C#:
public class Singleton { // Thread-safe oplossing om slechts één instantie aan te maken. private static Singleton _instance = new Singleton (); // Private constructor om te voorkomen dat anderen een instantie kunnen aanmaken. private Singleton () { } // Via een static read-only property kan de instantie benaderd worden. public static Singleton Instance { get { return _instance; } } }
C# (met generics) [bewerken]
Een thread-safe voorbeeld met een luie initialisatie.
/// <summary> /// Generic class implements singleton pattern. /// </summary> /// <typeparam name="T"> /// Reference type. Important: Must have private constructor (not public). /// </typeparam> public class Singleton<T> where T : class { protected Singleton () { } public static T Instance { get { return SingletonCreator.instance; } } class SingletonCreator { // static SingletonCreator() { } redundant as it is created by the compiler automatically internal static readonly T instance = typeof(T).InvokeMember(typeof(T).Name, BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic, null, null, null) as T; } }
PHP 5 [bewerken]
Singleton-patroon in PHP 5:
class Singleton { // object instance private static $instance; private function __construct() {} private function __clone() {} public static function getInstance() { if (!Singleton::$instance instanceof self) { Singleton::$instance = new self(); } return Singleton::$instance; } }
Ruby [bewerken]
Singleton-patroon in Ruby
require 'singleton' class Singleton include Singleton end
Scala [bewerken]
Singleton-patroon in Scala is een taalelement.
object Singleton // Gebruik: val singleton = Singleton
Thread safety gegarandeerd
C++ [bewerken]
Singleton-patroon in C++
.h
class CSingleton { protected: CSingleton(); public: virtual ~CSingleton(); static CSingleton* Instance(); private: static CSingleton* m_pSingleton; };
.cpp
//Definieer static om linkererrors te voorkomen CSingleton* CSingleton::m_pSingleton = NULL; CSingleton::CSingleton() { } CSingleton::~CSingleton() { } CSingleton* CSingleton::Instance() { if(m_pSingleton == NULL) m_pSingleton = new CSingleton; return m_pSingleton; }
Bronnen, noten en/of referenties
|