miércoles, 10 de noviembre de 2010

El patrón Singleton

Buenas de nuevo estimados amigos!!!!!! Una vez creado el blog y habiendo hecho la entrada  de bienvenida, ha llegado el momento de editar la primera entrada sobre informática (comprendo que a mis queridos lectores que no les guste la informática les puede resultar aburrida, pero oye, que un poco de culturilla general no viene mal a nadie, ya se hablará de otros temas).

El tema de esta entrada va a ser sobre un patrón de diseño en programación orientada a objetos llamado Singleton. 

Por motivos de seguridad o simplemente de diseño, en muchas ocasiones, se hace necesario tener una sola instancia de una determinada clase, instancia la cual será utilizada por el resto de las clases. Ejemplos de estas clases pueden ser un Agente de base de datos o una clase Proxy (otro patrón de diseño que ya explicaré en su momento) que acceda a otro sistema externo. Esta problemática la resuelve el patrón Singleton. En el siguiente código fuente muestro la cabecera de una clase Singleton en C++.

class Singleton
{
 protected:
  static Singleton * instancia;
  Singleton();
 public:
  static Singleton * getInstancia();
  void Metodo1();
  void Metodo2();

};

Se pueden ver una serie de particularidades que diferencian a este tipo de clases. 
  1. La primera es que el constructor es protegido. Lógico puesto que lo que se pretende es que ninguna otra clase pueda crear instancias de la clase Singleton. 
  2. La segunda es que existe un puntero a una instancia de la misma clase (instancia) que será la única que se pueda utilizar en toda la aplicación.
  3. La tercera es que existe un método de acceso a esa instancia (getInstancia). Gracias a este método se podrá acceder a los otros métodos públicos de la clase. 
En el siguiente código se puede ver el fichero de implementación de la clase Singleton:
#include "Singleton.h"

/* INICIALMENTE LA INSTANCIA ES NULA PARA NO OCUPAR ESPACIO EN MEMORIA 
 SI NO FUERA ACCEDIDA EN TODA LA EJECUCIÓN DE MEMORIA */
Singleton * Singleton::instancia = NULL;

/* CONSTRUCTOR DE LA CLASE */
Singleton::Singleton()
{
 
}

/* MÉTODO A TRAVES DEL CUAL SE ACCEDERÁ A LA ÚNICA INSTANCIA */
Singleton * Singleton::getInstancia()
{
 if(this->instancia == NULL)
 {
  this->instancia = new Singleton();
 }
 return this->instancia;
}

/* MÉTODO 1 AL CUAL SOLO SE PODRÁ ACCEDER POR LA ÚNICA INSTANCIA */
void Singleton::Metodo1()
{
 printf("Estamos en metodo 1");
}

/* MÉTODO 2 AL CUAL SOLO SE PODRÁ ACCEDER POR LA ÚNICA INSTANCIA */
void Singleton::Metodo2()
{
 printf("Estamos en metodo 2");
}
  
Vemos que la variable instancia se inicializa por defecto a NULL, para que en el caso de que no se haga uso de la clase en toda la aplicación, no ocupe lugar en memoria principal.

Cuando se llama la primera vez al método getInstancia se reserva memoria a la instancia de la clase y se retorna el puntero. Las siguientes veces que se llame al método simplemente se retornará dicho puntero de la instancia recién creada.

A continuación, añado un fragmento de como  se llamaría a esta clase para acceder a sus funciones o métodos:

#include "Singleton.h"

int main()
{
 /* LLAMADA DESDE LA ÚNICA INSTANCIA DEL SINGLETON A SU MÉTODO 1 */
 Singleton::getInstancia()->Metodo1();
 /* LLAMADA DESDE LA ÚNICA INSTANCIA DEL SINGLETON A SU MÉTODO 2 */
 Singleton::getInstancia()->Metodo2();

 return 0;
}

Por último, dejo un ejemplo de como se implementaría la misma clase en java.

public class Singleton{

 /* INSTANCIA DE ACCESO A LA CLASE */
 protected static Singleton instancia;
 
 /* CONSTRUCTOR DE LA CLASE */
    protected Singleton(){

    }
 
 /* MÉTODO DE ACCESO A LA INSTANCIA */
 public static Singleton getSingleton() {
  if (instancia==null) 
   instancia = new Singleton();
  
  return instancia;
 }
 /**********************/
 /* MÉTODOS DE LA CLASE */
 /**********************/
 public void Metodo1(){
  System.out.println("Estamos en Método 1");
 }
 
 public void Metodo2(){
  System.out.println("Estamos en Método 2");
 }
}


Con este último fragmento finalizo la entrada sobre el patrón Singleton, esperando que pueda ser de ayuda. 
Como ser humano que soy y por lo tanto bastante imperfecto (todo sea dicho), os invito a que cualquier fallo que encontréis o cualquier apunte que queráis añadir lo hagáis público. Por eso os invito a ir dejando vuestros comentarios.

Un saludo y hasta la próxima.


1 comentario:

  1. Sencillo y claro. Todo un lujo para mis ojos.

    Esperando el próximo patrón con impaciencia.

    ResponderEliminar