21 diciembre 2005

Patrón Singleton

Supongamos que estamos en un proyecto con varias personas. Nuestra aplicación se conecta con un socket con otro programa que corre en algún lado. Alguien de nuestro proyecto hace la clase Conexion que dentro establece la conexión a través de socket con el otro programa. A esta clase se le pone los métodos enviaMensaje() y un avisameCuandoLLegueMensaje(), de forma que todo el mundo pueda enviar mensajes por la conexión y ser avisado cuando llegue algún mensaje en el que tenga interés.

Todos los que necesitan esta Conexion deben poner en sus clases un método tomaConexion() que reciba como parámetro la Conexion, y guardarsela para enviar mensajes o recibirlos.

Además, como es habitual, la documentación de diseño no es lo suficientemente buena y alguno de nuestros programadores despistados, se olvida de poner el método y decide simplemente hacer un new Conexion().

Por un lado tenemos el rollo de andar pasando la Conexion a todo el mundo. Por otro lado, nuestro programa misteriosamente funciona mal porque hay varias clases Conexion instanciadas y el otro programa piensa que somos varios clientes y la mensajería que recibimos no es del todo coherente (eso si no tenemos directamente problemas con la conexión al haber varios peleándose por la misma).

El patrón Singleton nos ayuda a que nuestra instancia Conexion sea única, a la vez que la hace accesible a todo el mundo sin necesidad de andar pasándola.

Para ello debemos hacer varias cosas:
  • La clase Conexion debe tener un constructor privado, de forma que nadie, salvo ella misma, pueda instanciarla.
  • La clase Conexion debe tener un atributo estático privado, inicialmente a null. En él se guardará la única instancia de esta clase.
  • La clase Conexion debe tener un método estático público dameConexion(). Este método crea una instancia de Conexion la primera vez que se le llama y la guarda en el atributo estatico. Luego devuelve dicho atributo estático en el return.
Puede ser algo como esto

public class Conexion
{

private Conexion()
{
...
}

private static Conexion laConexion = null;

public Conexion dameConexion()
{
if (laConexion == null)
laConexion = new Conexion();
return laConexion;
}

}

Cuando alguien necesita una conexion, simplemente debe hacer

Conexion miConexion = Conexion.dameConexion();

y tiene accesible la única instancia de Conexion que hay.

6 comentarios:

Anónimo dijo...

El patrón singleton tambien es muy util cuando tenemos datos en una aplicación que van a ser compartidos por muchas clases de la misma y no los queremos cargar en memoria todas las veces que los vayamos a utilizar porque nos ocupa mucho tiempo. Por ejemplo si tenemos un registro con los datos
Nombre
Apellidos
Teléfono
...
y estos no van a variar en toda la ejecución de la aplicación utilizamos un singleton y sólo se cargarán la primera vez

Anónimo dijo...

Tambien existen un par de variantes del Singlenton, que se denominan Singlenton Multiple y Singlentos Polimorfico.

Un ejemplo del segundo caso lo encontramos en el caso de un programa matematico que defina constantes para su uso. Se puede definir una clase abstracta que contenga la interfaz de la constante y subclases que definan cada una de las constantes que se desea trabajar, pi, phi, e, etc (claro hay soluciones mas rapidas, pero esta es una que brinda la elegancia de la orientacion a objetos).

Un ejemplo del otro tipo de singlenton podria darse en un programa de geografia de un pais puntual. En el caso de venezuela el pais cuenta con 24 estados. Nuestra clase Singlentos iria generando objetos a medida que sea necesario obtener un estado. Fijese en este caso que pueden accederse a los datos de dos maneras: Con un indice que indica cual es la instancia del objeto a trabajar o de manera aleatoria. Si se emplea la forma aleatoria el metodo dame_instancia (canocido como Unique_Instance en la galeria de patrones de gamma) devolveria objetos nuevos hasta llenar el tope del vector y cuando este lleno devuelve objetos creados. En el caso del indice seria como tener n objetos singlentos de una sola instancia.

Debe tenerse en cuenta que estas son adaptaciones del patron original, por eso debe tratar el constructor de acuerdo al caso para mantener consistencias con el comportamiento deseado

Anónimo dijo...

hola a todos, soy nuevo en esto y solo me gustaría comentar que otra de los usos que se me ocurre es para la conexión a una base de datos, pero no se que tan buena idea, sea esta. En este momento estoy trabajando en una clase asi, en cuanto la tenga lista si quieren la publico para ver si sirve de algo

chuidiang dijo...

Hola:

Si estamos hablando de java, para el tema de conexión a base de datos hay varias opciones. Entre ellas, el patrón singleton ya lo implementado en algunas librerías o incluso dentro del mismo jar con el driver de la base de datos. Echa un ojo a este enlace pool de conexiones

Se bueno.

Anónimo dijo...

Y quien se encarga de cerrarla? El timeout? Como sabemos si la conexion sigue activa a la hora de retornarla?

Anónimo dijo...

En el metodo dameConexion te falto poner que es static. Saludos