En la programación orientada a objetos , el patrón singleton es un patrón de diseño de software que restringe la instanciación de una clase a una instancia singular. Uno de los conocidos patrones de diseño de la "Banda de los cuatro" , que describe cómo resolver problemas recurrentes en software orientado a objetos. [1] El patrón es útil cuando se necesita exactamente un objeto para coordinar acciones en un sistema.
Más específicamente, el patrón singleton permite que las clases: [2]
El término proviene del concepto matemático de singleton .
Los singletons suelen preferirse a las variables globales porque no contaminan el espacio de nombres global (o el espacio de nombres que lo contiene). Además, permiten una asignación e inicialización diferidas , mientras que las variables globales en muchos lenguajes siempre consumirán recursos. [1] [3]
El patrón singleton también se puede utilizar como base para otros patrones de diseño, como los patrones de fábrica abstracta , método de fábrica , constructor y prototipo . Los objetos de fachada también suelen ser singletons porque solo se necesita un objeto de fachada.
El registro es un caso de uso real común para singletons, porque todos los objetos que desean registrar mensajes requieren un punto de acceso uniforme y escriben conceptualmente en una única fuente. [4]
Las implementaciones del patrón singleton garantizan que solo exista una instancia de la clase singleton y normalmente proporcionan acceso global a esa instancia.
Normalmente, esto se logra mediante:
La instancia generalmente se almacena como una variable estática privada ; la instancia se crea cuando se inicializa la variable, en algún momento antes de que se llame por primera vez al método estático.
Esta implementación de C++11 se basa en la implementación anterior a C++98 del libro [ cita requerida ] .
#include <flujo de datos> class Singleton { public : // define una operación de clase que permite a los clientes acceder a su instancia única. static Singleton & get () { // puede ser responsable de crear su propia instancia única. if ( nullptr == instance ) instance = new Singleton ; return * instance ; } Singleton ( const Singleton & ) = delete ; // regla de tres Singleton & operator = ( const Singleton & ) = delete ; static void destruct () { delete instance ; instance = nullptr ; } // la interfaz existente va aquí int getValue () { return value ; } void setValue ( int value_ ) { value = value_ ; } private : Singleton () = default ; // sin constructor público ~ Singleton () = default ; // sin destructor público static Singleton * instance ; // declaración de la variable de clase int value ; }; Singleton * Singleton :: instance = nullptr ; // definición de la variable de clase int main () { Singleton :: obtener (). setValue ( 42 ); std :: cout << "valor=" << Singleton :: obtener (). getValue () << '\n' ; Singleton :: destruct (); }
La salida del programa es
valor = 42
Esta es una implementación del singleton de Meyers [5] en C++11. El singleton de Meyers no tiene método de destrucción. La salida del programa es la misma que la anterior.
#include <flujo de datos> clase Singleton { público : Singleton estático y get () { instancia de Singleton estático ; instancia de retorno ; } int getValue () { valor de retorno ; } void setValue ( int valor_ ) { valor = valor_ ; } privado : Singleton () = predeterminado ; ~ Singleton () = predeterminado ; int valor ; }; int main () { Singleton :: obtener (). setValue ( 42 ); std :: cout << "valor=" << Singleton :: obtener (). getValue () << '\n' ; }
Una implementación singleton puede utilizar una inicialización diferida en la que la instancia se crea cuando se invoca por primera vez el método estático. En programas multiproceso , esto puede provocar condiciones de carrera que resulten en la creación de múltiples instancias. El siguiente ejemplo de Java 5+ [6] es una implementación segura para subprocesos , que utiliza una inicialización diferida con bloqueo de doble verificación .
clase pública Singleton { instancia Singleton privada estática volátil = nula ; Singleton privado () {} público estático Singleton getInstance () { if ( instancia == null ) { sincronizado ( Singleton . class ) { if ( instancia == null ) { instancia = new Singleton (); } } } return instancia ; } }
Algunos consideran que el singleton es un antipatrón que introduce un estado global en una aplicación, a menudo de forma innecesaria. Esto introduce una posible dependencia del singleton por parte de otros objetos, lo que requiere el análisis de los detalles de implementación para determinar si realmente existe una dependencia. [7] Este mayor acoplamiento puede introducir dificultades con las pruebas unitarias . [8] A su vez, esto impone restricciones a cualquier abstracción que utilice el singleton, como evitar el uso simultáneo de varias instancias. [8] [9] [10]
Los singletons también violan el principio de responsabilidad única porque son responsables de hacer cumplir su propia singularidad junto con el desempeño de sus funciones normales. [8]
{{cite book}}
: CS1 maint: varios nombres: lista de autores ( enlace ){{cite book}}
: CS1 maint: varios nombres: lista de autores ( enlace )