Patrones de diseño creacionales: Singleton

Intención del patrón
  • Asegura que una clase tiene una única instancia y proveer un punto de acceso global a ella.
  • Inicialización "just-in-time" o inicialización "on first use" encapsulada.

Ejemplo de problema
La aplicación necesita una y sólo una instancia de un objeto. Adicionalmente se necesita una inicialización perezosa (lazy initialization) y acceso global.


Discusión
Hacer que una clase, con una única instancia de objeto, sea responsable de la creación, inicialización, acceso y ejecución. Declarar dicha instancia como un miembro private y static. Proveer una función pública y estática que encapsule todo el código de inicialización y además, provea acceso a la instancia.
El cliente invoca a la función de acceso (utilizando el nombre de la clase el operador correspondiente) cada vez que una referencia a la instancia es requerida.
Singleton debe ser considerado sólo si los siguientes tres criterios son satisfechos:
  • La propietadad de la instancia única no puede ser razonablemente asignada.
  • Se desea una inicialización perezosa.
  • El acceso global no sea provisto desde otro lugar.
Si la titularidad de la instancia, cuándo y cómo ocurre la inicialización y un acceso global no es importante, Singleton no es lo suficientemente interesante.
El patrón Singleton puede ser extendido para permitir el acceso a un número específico de instancias por parte de un aplicación.
Si se utiliza una "función de acceso de miembro estático" (static member function accessor) no se soportará subclases de la clase Singleton.

Estructura

La clase que soporta una única instancia, es la responsable del acceso y de la "inicialización ante el primer uso". Dicha instancia es un miembro privado de la clase y sólo puede accederse a través de un método estático público.

Ejemplo
El patrón Singleton asegura que la clase posee solo una instancia y provee un punto global de acceso a dicha instancia. El patrón lleva el nombre de un conjunto unitario (Singleton set) el cual es definido para ser un conjunto que contiene un solo elemento. La oficina del presidente de un País es un Singleton. La constitución de dicho país especifica los medios por los cuales se elige un presidente, limita la duración del mandato y define el orden de sucesión. Como resultado, no puede haber más de un presidente activo en un momento dado. Independientemente de la identidad personal del presidente, el título "presidente" es un punto de acceso global que identifica a la persona en la oficina.

Check list

  1. Definir un atributo estático privado en la clase.
  2. Definir un método público de acceso en dicha clase.
  3. Hacer una lazy initialization para la creación ante el primer uso en el método.
  4. Definir todos los contructores como private o protected.
  5. Los clientes sólo pueden usar la función de acceso para manipular el Singleton.


Reglas de oro

  • Abstract Factory, Builder y Protoype pueden usar Singleton en sus implementaciones.
  • Los objetos Facade son a menudo Singleton porque solo un objeto Facade es necesario.
  • Los objetos State son a menudo Singleton.
  • La ventaja de Singleton por sobre variables globales es que se puede estar absolutamente seguro de la cantidad de instancias cuando se usa Singleton y se puede cambiar de opinión y administrar cualquier número de instancias.
  • El patrón de diseño Singleton es uno de los más usados inapropiadamente. Singleton está destinado a ser usado cuando una clase debe tener exactamente una instancia, ni más, ni menos. Los diseñadores usan frecuentemente Singleton en un intento equivocado de reemplazar las variables globales. Un Singleton es, para los efectos, una variable global. El Singleton no acabo con lo Global, sino que simplemente lo renombra.
  • ¿Cuándo es innecesario un Singleton? Respuesta corta: la mayor parte del tiempo. Respuesta larga: cuando resulta simple pasar un objeto de recursos como referencia a otros objetos que lo necesitan en lugar de dejar accesos globales a dichos objetos de recursos. El problema real con los Singletons es que ellos brindan una buena excusa para no pensar cuidadosamente la apropiada visibilidad de un objeto. Encontrar el balance correcto de exposición y protección para un objeto es crítico para mantener la flexibilidad.
  • Un grupo de desarrolladores tenía el mal hábito de usar datos globales. Por este motivo crearon un grupo de estudio de Singleton. Detectaron que los Singleton aparecían por todos lados y ninguno de los problemas relacionados con los datos globales se fue. La respuesta a la pregunta de los datos globales no es "Crea un Singleton". La respuesta es "¿Por qué demonios se están usando datos globales?". Cambiar el nombre, no cambia el problema. De hecho, puede ser peor porque da la oportunidad de decir: "Bueno. yo no estoy haciendo eso; estoy haciendo esto" -aunque "eso" y "esto" sean la misma cosa.


Ejemplo de código en C#
using System;

class MainApp
{

  static void Main()
  {
    // Constructor is protected -- cannot use new 
    Singleton s1 = Singleton.Instance();
    Singleton s2 = Singleton.Instance();

    if (s1 == s2)
    {
      Console.WriteLine("Objects are the same instance");
    }

    // Wait for user 
    Console.Read();
  }
}

// "Singleton" 
class Singleton
{
  private static Singleton instance;

  // Note: Constructor is 'protected' 
  protected Singleton() 
  {
  }

  public static Singleton Instance()
  {
    // Use 'Lazy initialization' 
    if (instance == null)
    {
      instance = new Singleton();
    }

    return instance;
  }
}

0 comentarios:

Publicar un comentario

Muchas gracias por leer el post y comentarlo.

 
Copyright 2009 Programación SOLIDa
BloggerTheme by BloggerThemes | Design by 9thsphere