domingo, 31 de octubre de 2010

Patrón de diseño: Singleton

Saludos a todos. Hoy comenzaremos con el primer artículo acerca de los patrones de diseño. Para hoy hablaremos acerca del patrón de diseño Singleton.

Recuerdo en mi primer curso de Java, cuando nos asignan realizar un proyecto en este lenguaje, utilizando las ventajas de javax.swing, es decir interfaces gráficas, nuestro grupo creó un menú que llamaba a ventanas o diálogos. Se nos presentó el siguiente problema: Cuando se llamaba a una opción de menú se desplegaba una ventana auxiliar nueva, si de nuevo haciamos click sobre la misma opción, se mostraba otra ventana nueva igual a la anterior, es decir, se creaban duplicados o triplicados, lo cual para el proyecto no era lo adecuado. Empezamos a indagar que pasaba con tal caso, cómo podríamos hacer para que no sucediera esto y nuestro profesor muy sabiamente dijo, eso se resuelve con el patrón Singleton.

Empezamos a buscar información sobre este patrón y nos encontramos que la finalidad de este patrón es poder crear una sola instancia de una Clase, por lo tanto si se intentaba crear una nueva instancia se llamaba a la misma creada anteriormente, garantizando así la no duplicación. Ahora bien ahora lo que nos faltaría por ver es como puede llevarse a cabo este patrón:

Existen varias maneras de implementar Singleton, aquí va la más utilizada:



public class ClaseSingleton {

private static ClaseSingleton instancia = null;

private ClaseSingleton() { } //constructor privado

public static ClaseSingleton getInstanciaUnica() {

if (instancia == null) {
instancia = new ClaseSingleton();
}
return instancia;
}
}


Como puede verse existe en la clase un constructor privado, esto se hace con la finalidad de que sólo la clase singleton pueda crear instancias. Existe también un método getInstanciaUnica que crea la instancia si aun no ha sido creada, pero si ya fue creada una, devuelve la misma creada anteriormente.

Veamos un ejemplo con las Ventanas de javax.swing:
Clase Principal: Con Main:


package patronesdisenio;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class VentanaPrincipal extends JFrame
implements ActionListener {

public VentanaPrincipal() {
super("Ventana Principal");
JButton boton = new JButton("Nueva Ventana");
Container contenedor = getContentPane();
contenedor.add(boton, BorderLayout.SOUTH);
boton.addActionListener(this);
setSize(600, 600);
setVisible(true);
}

public static void main(String[] args) {
VentanaPrincipal app = new VentanaPrincipal();
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public void actionPerformed(ActionEvent e) {
VentanaAuxiliar.getVentanaAuxiliarUnica();
}
}


Aquí la Ventana Auxiliar a llamar (Singleton)


package patronesdisenio;

import javax.swing.JDialog;

public class VentanaAuxiliar extends JDialog{

public static VentanaAuxiliar vtnUnica = null;

private VentanaAuxiliar(){ }

public static VentanaAuxiliar
getVentanaAuxiliarUnica(){
if(vtnUnica == null){
vtnUnica = new VentanaAuxiliar();
vtnUnica.setTitle("Ventana Auxiliar");
vtnUnica.setSize(490, 400);
vtnUnica.setVisible(true);
return vtnUnica;
}
return vtnUnica;
}
}


De esta manera cuando se llame a la ventana auxiliar desde la ventana principal con el botón inferior, no se generará ventana duplicada ya que Ventana auxiliar es singleton.

4 comentarios:

edison dijo...

saludos Kelvin
te agrdesco mucho por la atencion prestada.... y seguro que tu articulo me sirvio de mucho muy buenos.....
saludos y hasta pronto

Anónimo dijo...

Hola.

Solo comentar que el patron singleton debe usarse con cuidado. Eh escuchado que no favorece el desarrollo guiado por pruebas.

Saludos cordiales.

Kelvin dijo...

Hola Anónimo.

Bueno habrá que fundamentar mejor porque no favorece el desarrollo guiado por pruebas, pero el patrón singleton es utilizado cuando quiero crear una sola instancia de una clase. Es necesario en estos casos utilizar esta metodología.

No veo porque no pueda favorecer. Si tienes una información más completa, por favor, compártela.
En este caso la pregunta sería. ¿El desarrollo creado por pruebas necesita mas de una instancia?, de ser así, por supuesto Singleton no le favorece.

EzeQ22 dijo...

Hola como estas Kelvin, por lo que veo paso mucho tiempo desde que hiciste este post, pero lo implemente y me surgieron algunas dudas...
Mejor dicho al implementarlo no me da el resultado esperado, por ej cuando yo llamo a la ventana a la cual le implemento Singleton ésta me abre una sola vez sin problemas, pero totalmente vacía... no encuentro la forma de que me cargue los componentes visuales que ella contiene...
Ademas una vez cerrada la ventanaSingleton, por mas que vuelva a clickear en el boton que la lanza, la ventanaSingleton no vuelve a aparecer...
Podrias ayudarme con mi problema? desde ya muchas gracias.
Pd: el patron esta imple,mentado tal cual tu codigo, saludos.