Singleton
De Wikipedia, la enciclopedia libre
El patrón de diseño singleton (instancia única) está diseñado para restringir la creación de objetos pertenecientes a una clase o el valor de un tipo a un único objeto.
Su intención consiste en garantizar que una clase sólo tenga una instancia y proporcionar un punto de acceso global a ella.
El patrón singleton se implementa creando en nuestra clase un método que crea una instancia del objeto sólo si todavía no existe alguna. Para asegurar que la clase no puede ser instanciada nuevamente se regula el alcance del constructor (con atributos como protegido o privado).
La instrumentación del patrón puede ser delicada en programas con múltiples hilos de ejecución. Si dos hilos de ejecución intentan crear la instancia al mismo tiempo y esta no existe todavía, sólo uno de ellos debe lograr crear el objeto. La solución clásica para este problema es utilizar exclusión mutua en el método de creación de la clase que implementa el patrón.
Las situaciones más habituales de aplicación de este patrón son aquellas en las que dicha clase controla el acceso a un recurso físico único (como puede ser el ratón o un archivo abierto en modo exclusivo) o cuando cierto tipo de datos debe estar disponible para todos los demás objetos de la aplicación.
El patrón singleton provee una única instancia global gracias a que:
- La propia clase es responsable de crear la única instancia.
- Permite el acceso global a dicha instancia mediante un método de clase.
- Declara el constructor de clase como privado para que no sea instanciable directamente.
Contenido |
[editar] Ejemplo de implementación
[editar] Java
Una implementación correcta en el lenguaje de programación Java para programas multi-hilo es la solución conocida como "inicialización bajo demanda" sugerida por Bill Pugh:
public class Singleton { // El constructor privado no permite que se genere un constructor por defecto // (con mismo modificador de acceso que la definicion de la clase) private Singleton() {} public static Singleton getInstance() { return SingletonHolder.instance; } private static class SingletonHolder { private static Singleton instance = new Singleton(); } }
A continuación, un ejemplo correcto de inicialización diferida. Se deja para comentar un error común en Java al no tener en cuenta la sincronización de métodos.
public class Singleton { private static Singleton INSTANCE = null; // Private constructor suppresses private Singleton() {} // creador sincronizado para protegerse de posibles problemas multi-hilo // otra prueba para evitar instanciación múltiple private synchronized static void createInstance() { if (INSTANCE == null) { INSTANCE = new Singleton(); } } public static Singleton getInstance() { if (INSTANCE == null) createInstance(); return INSTANCE; } }
[editar] C#
Un ejemplo correcto de inicialización diferida en C# sería:
using System.Runtime.CompilerServices; public class Singleton { private static Singleton Instance = null; // El constructor privado no permite que se genere un constructor por defecto // (que es público) private Singleton() {} // creador sincronizado para protegerse de posibles problemas multi-hilo // otra prueba para evitar instanciación múltiple [MethodImpl(MethodImplOptions.Synchronized)] private static void CreateInstance() { if (Instance == null) { Instance = new Singleton(); } } public static Singleton GetInstance() { if (Instance == null) CreateInstance(); return Instance; } } // Clase de prueba public class Prueba { private static void main(string[] args) { //Singleton s0 = new Singleton(); ----Error Singleton s1 = Singleton.GetInstance(); Singleton s2 = Singleton.GetInstance(); if(s1==s2) { // Misma instancia } } }
[editar] C++
Una solución posible en C++ (conocida como el singleton de Meyers) en la cual el singleton es un objecto local estático (notar que esta solución no es segura en programas multi-hilo):
template<typename T> class Singleton { public: static T& Instance() { static T laInstanciaSingleton; //asumir T posee un constructor por defecto return laInstanciaSingleton; } }; class SoloUno : public Singleton<SoloUno> { friend class Singleton<SoloUno>; //para dar acceso al constructor privado de SoloUno //..definir aquí el resto de la interfaz };
[editar] Python
El siguiente es un ejemplo de implementación de Singleton en Python (no es thread safe)
class Singleton (object): instance = None def __new__(cls, *args, **kargs): if cls.instance is None: cls.instance = object.__new__(cls, *args, **kargs) return cls.instance #Usage mySingleton1 = Singleton() mySingleton2 = Singleton() #mySingleton1 y mySingleton2 son la misma instancia assert mySingleton1 is mySingleton2
Y otra posibilidad interesante es implementarlo como una metaclase:
class Singleton(type): def __init__(cls, name, bases, dct): cls.__instance = None type.__init__(cls, name, bases, dct) def __call__(cls, *args, **kw): if cls.__instance is None: cls.__instance = type.__call__(cls, *args,**kw) return cls.__instance class A: __metaclass__ = Singleton # Definir aquí el resto de la interfaz a1 = A() a2 = A() assert a1 is a2
[editar] Visual Basic. NET
Una implementación del patrón singleton en Visual Basic. NET es la siguiente:
Public Class Singleton Private Sub New() End Sub Private Shared _instancia As Singleton Public Shared ReadOnly Property Instancia() As Singleton Get If _instancia Is Nothing Then _instancia = New Singleton End If Return _instancia End Get End Property End Class
[editar] PHP5
Una implementación del patrón singleton en PHP5 es la siguiente:
<?php class Ejemplo { // Contenedor Instancia de la Clase private static $instance; // A private constructor; previene creacion de objetos via new private function __construct() { echo 'Soy el constructor'; } // EL metodo singleton public static function singleton() { if (!isset(self::$instance)) { $c = __CLASS__; self::$instance = new $c; } return self::$instance; } // Clone no permitido public function __clone() { trigger_error('Clone no se permite.', E_USER_ERROR); } } ?>
[editar] Patrones relacionados
- Abstract Factory: muchas veces son implementados mediante Singleton, ya que normalmente deben ser accesibles públicamente y debe haber una única instancia que controle la creación de objetos.
- Monostate: es similar al singleton, pero en lugar de controlar el instanciado de una clase, asegura que todas las instancias tengan un estado común, haciendo que todos sus miembros sean de clase.f
[editar] Enlaces externos
- Explicación del patrón singleton.
- A Q&A page (java.sun.com)
- PEC(TM), compilador que garantiza la correcta instrumentación del patrón singleton y de otros patrones.
- Data&Object Factory, explicación e implementación en C# del patrón singleton.
- El Patron Singleton (MSDN), artículo de Leon Welicki donde se explica e implementa este patrón utilizando .NET.
- Patrón Singleton explicado en video, artículo de Lucas Ontivero donde explica mediante tres videos de 8 minutos 3 implementaciones del patrón Singleton en CSharp (nivel básico)

