Singleton

RECU-0202 (Recurso Patrón)

Descripción

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. No se encarga de la creación de objetos en sí, sino que se enfoca en la restricción en la creación de un objeto.

Nombre

También es conocido como Singular o Único.

Clasificación

Patrón creacional

Motivación

En algunas ocasiones es muy importante poder garantizar que solo existe una instancia de una clase. Imaginamos la situación de varias impresoras disponibles cuando solo existe un pool que maneja la impresión. Es necesario asegurar que solo existe un objeto dentro del gestor de la impresión. Basándonos en el ejemplo, necesitamos un patrón que nos permita controlar las situaciones que exigen un control de acceso a una instancia bandera, muy habitual en sistemas concurrentes.

Aplicabilidad

Este patrón es aplicable en sistemas en los que se desea poder garantizar que solo existe una instancia de una clase.

Estructura

 

Participantes

  • Singleton: Define una operación de clase getInstance que permite a los clientes acceder a ella y ademas, es responsable de la creación de la instancia única.

Colaboraciones

Los clientes acceden a la instancia única solamente a traves de la operación getInstance.

Consecuencias

El uso del patrón Singleton proporciona los siguientes beneficios:

  • Reduce el espacio de nombres. El patrón es una mejora sobre las variables globales. Ya no se reservan nombres para las variables globales, ahora solo existen instancias
  • Controla el acceso a la instancia única, porque la clase Singleton encapsula la única instancia. Asi se obtiene control sobre cómo y cuándo se accede a ella.
  • Permite el refinamiento de las operaciones y la representación.
  • Permite un numero variable de instancias. El patron es facilmente configurable para permitir más de una instancia
  • Más flexible que las operaciones de clases

Implementación

Siempre que se crea un objeto nuevo (en Java, con la palabra reservada new) se invoca al constructor del objeto para que cree una instancia. Por lo general, los constructores son públicos. El Singleton lo que hace es convertir el constructor en privado, de manera que nadie lo pueda instanciar.

Entonces, si el constructor es privado, ¿cómo se instancia el objeto? Pues a través de un método público y estático de la clase. En este método se revisa si el objeto ha sido instanciado antes. Si no ha sido instanciado, llama al constructor y guarda el objeto creado en una variable estática del objeto. Si el objeto ya fue instanciado anteriormente, lo que hace este método es devolver la referencia al estado creado anteriormente.

Hay que tener especial cuidado cuando el Singleton se utiliza en un ambiente multihilos, porque puede crear problemas si no se implementa de la manera adecuada. En Java es posible que tengamos que realizar una "incialización bajo demanda" para evitar problemas en este sentido. Concluyendo, la idea central del Singleton es esa: asegurar de que exista tan solo una instancia del objeto en toda la aplicación. Es un patrón muy aplicado en Java, aunque, como todos los patrones, se puede implementar en cualquier lenguaje orientado a objetos.

Para realizar una buena implementación del patrón Singleton se recomienda.

  • Ocultar el constructor.
  • Declarar como estático el método getInstance.
  • En ambiente concurrentes es necesario usar mecanismos que aseguren la atomicidad del método getInstance.

Código de ejemplo

Implementación del patrón bajo demanda. Tenemos el código siguiente:

public class Singleton {
 
     static private Singleton singleton = null;
 
     private Singleton() { }
 
     static public Singleton getSingleton() {
 
         if (singleton == null) {
             singleton = new Singleton();
         }
         return singleton;\\
     }
 
     public String metodo() {\\
         return "Singleton instanciado bajo demanda";
     }
 
 }

Esta implementación se caracteriza porque nuestra instancia única se crea cuando se usa por primera vez – bajo demanda – gracias a una sentencia condicional. En el a continuación eliminaremos esto, no por ser incorrecto, sino porque en general no es necesario. La condición del método singleton() puede ser eliminada. Dicha condición se va a evaluar a cierto siempre salvo la primera vez. Además, el cargador de clases de Java, cuando referenciamos una clase no cargada anteriormente, se ocupa de cogerla de disco y cargarla en memoria inicializando sus miembros static.Por tanto el siguiente código actúa exactamente igual que el caso 1, creando la instancia en la primera invocación pero eliminando la condición.

public class Singleton {
 
     static private Singleton singleton = new Singleton();\\
 
     private Singleton() { }
 
     static public Singleton getSingleton() {
         return singleton;
     }
     public String metodo() {\\
         return "Singleton ya instanciado";\\
     }
 
 }

tenemos que solicitar la instancia única del mismo. Habitualmente se hace de dos formas diferentes, la primera se usa en llamadas puntuales.

Singleton.getsingleton().metodo();

La segunda se usa cuando vamos a invocar nuestro Singleton varias veces, evitando llamadas innecesarias a métodos. Este tipo de singleton es un objeto como otro cualquiera, así que puede ser referenciado sin problemas.

Singleton s = Singleton.getSingleton();
 s.metodo();

Usos conocidos

Varios patrones pueden implementarse conjuntamente con el patrón Singleton.

Contenidos relacionados

Recursos
Área: Desarrollo » Patrones de Diseño
Código Título Tipo Carácter
RECU-0013 Patrones de diseño Ficha Recomendado
RECU-0190 Factoría Patrón Recomendado
RECU-0191 Factoría Abstracta Patrón Recomendado
RECU-0199 Prototipo Patrón Recomendado