Patrón Singleton en Java, con ejemplos


El proyecto de este post los puedes descargar pulsando AQUI.

En este tutorial vamos a hablar del patrón de diseño "Singleton", que en ingeniería del software es un patrón diseñado para limitar la creación de objetos pertenecientes a una clase. El objetivo de este patrón es el de garantizar que una clase solo tenga una instancia (o ejemplar) y proporcionar un punto de acceso global a ella. Esta patrón; por ejemplo, suele ser utilizado para las conexiones a bases de datos.

Este patrón se implementa haciendo privado el constructor de la clase y creando (en la propia clase) un método que crea una instancia del objeto si este no existe. Veamos a continuación un ejemplo de este patrón en el que vamos a crear una clase llamada "SoyUnico" con un constructor que va a ser privado y un método llamado 'getSingletonInstance()' que será el encargado de crear una instancia de esta clase si no se ha creado todavía:

public class SoyUnico {

    private String nombre;
    private static SoyUnico soyUnico;

    // El constructor es privado, no permite que se genere un constructor por defecto.
    private SoyUnico(String nombre) {
        this.nombre = nombre;
        System.out.println("Mi nombre es: " + this.nombre);
    }

    public static SoyUnico getSingletonInstance(String nombre) {
        if (soyUnico == null){
            soyUnico = new SoyUnico(nombre);
        }
        else{
            System.out.println("No se puede crear el objeto "+ nombre + " porque ya existe un objeto de la clase SoyUnico");
        }
        
        return soyUnico;
    }
    
    // metodos getter y setter

}

Vemos como al llamar al método 'getSingletonInstance()'  pregunta si el atributo 'soyUnico' es null o no, y si no lo es lo crea. En el caso de que ya haya sido creado no imprimirá un mensaje por pantalla diciendonos que ya existe un objeto de esa clase.

Vamos a ver como efectivamente nos crea un solo objeto, ejecutando el siguiente código en el que llamamos dos veces el método 'getSingletonInstance()':

public class Main {

    public static void main(String[] args) {
        
        SoyUnico ricardo = SoyUnico.getSingletonInstance("Ricardo Moya");
        SoyUnico ramon = SoyUnico.getSingletonInstance("Ramón Invarato");
        
        // ricardo y ramon son referencias a un único objeto de la clase SoyUnico
        System.out.println(ramon.getNombre());
        System.out.println(ricardo.getNombre());   
    }
}

Como salida a este código tenemos lo siguiente:

Mi nombre es: Ricardo Moya
No se puede crear el objeto Ramón Invarato porque ya existe un objeto de la clase SoyUnico
Ricardo Moya
Ricardo Moya

Vemos como efectivamente cuando no hay un objeto de la clase "SoyUnico", lo crea y si lo quiere volver a crear, el método nos dice que ya hay otro creado pero le asigna la referencia al objeto, es decir que las variable 'ricardo' y 'ramon' referencian al mismo y único objeto de la clase "SoyUnico"; tal y como podemos ver al preguntar por el atributo 'nombre' de la clase.

Por último este patrón no quedaria perfectamente implementado si no controlamos la copia (o clone) de los objetos de esta clase; por ello es importante sobrescribir el método 'clone()', para que cuando se quiera clonar este objeto se lance una excepción. Este método lo sobrescribimos de la siguiente forma:

//Sobreescribimos el método clone, para que no se pueda clonar un objeto de esta clase
@Override
public SoyUnico clone(){
    try {
        throw new CloneNotSupportedException();
    } catch (CloneNotSupportedException ex) {
        System.out.println("No se puede clonar un objeto de la clase SoyUnico");
    }
    return null; 
}

Veamos que pasa si intentamos clonar el objeto de la clase "SoyUnico":

public class Main {

    public static void main(String[] args) {
        
        SoyUnico ricardo = SoyUnico.getSingletonInstance("Ricardo Moya");

        try{
            SoyUnico richard = ricardo.clone();
            System.out.println(richard.getNombre());
        }catch (NullPointerException ex){
            ex.printStackTrace();
        }
    }
}

Vemos que nos lanza una excepción y no nos permite clonar ese objeto.

Mi nombre es: Ricardo Moya
No se puede clonar un objeto de la clase SoyUnico
java.lang.NullPointerException
	at Main.Main.main(Main.java:21)

En resumen, en este tutorial se ha puesto un ejemplo muy sencillo para ver el funcionamiento del patrón "Singleton" que es un patron de diseño muy utilizado (quizas el que más), aplicable en los casos en los que solo queremos tener un único objeto de la clase que implementamos.

Comparte esta entrada en:
Safe Creative #1401310112503
Patrón Singleton en Java, con ejemplos por "www.jarroba.com" esta bajo una licencia Creative Commons
Reconocimiento-NoComercial-CompartirIgual 3.0 Unported License.
Creado a partir de la obra en www.jarroba.com

5 comentarios en “Patrón Singleton en Java, con ejemplos”

  1. Es aconsejable utilizar el patrón singleton para un sistema web?

    creo que podría generar bloqueos si solo se usa una conexión.

  2. Hola! Y feliz Navidad!

    Entonces, en realidad si podríamos clonarlo pero estaría conceptualmente mal, no??

     

    Saludos

    Agustín

    1. Hola Agustín.

      La idea del patron singleton es que solo haya un objeto de esa clase. Si lo clonamos obviamente habrá 2 o más objetos con lo cual no tendría sentido utilizar este patrón. No es que conceptualmente este mal, pero haciendo un clone no estarías utilizando este patrón. Normalmente cuando he utilizado este patrón no he implementado la excepción del clone ya que asumo que estoy utilizando ese patrón y no voy a clonar ese objeto, pero lo pongo en este tutorial por si acaso.

      Saludos

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies

ACEPTAR
Aviso de cookies