01 octubre 2012

Singleton


Estoy preparando una entrada sobre cómo parsear un fichero de properties dividido por secciones, y mientras estaba escribiendo el código de ejemplo, se me ha venido a la cabeza que lo mejor para implementar un objeto de propiedades, es el que tenga una única instancia dentro del código. Es por esto, por lo que lo mejor siempre es crear un objeto Singleton.


Es útil, dado que una aplicación se arrancará, y lo primero que hará es leer un fichero de propiedades para empezar a funcionar. Pero dicha aplicación puede tener varias instancias, o que durante la ejecución, necesite echar mano de esas propiedades. Así pues, si ya hemos leído y parseado todo el contenido de ese objeto de propiedades ¿Para qué volverlo a leer si podemos compartir un único objeto entre todas las clases?

Después del salto os muestro un codiguito de ejemplo de cómo declarar, instanciar y usar un ejemplo de tipo singleton.



package es.snippetea;
/**
*  Clase que ilustra el cómo crear un objeto de instancia única(Singleton) 
* y de cómo obtenerle.
*
*  En el caso de que se requiriera algún parámetro de inicialización, el método  
* se pasaría a
 declarar público de la siguiente manera:
*
*  public static final init(Param a) {}
*
*  y habrá de ser llamado por el usuario con ése parámetro. El contenido del 
* código encargado de
 utilizar ese parámetro, estará en el constructor que se 
* pasaría a declararse
*
*  private SingletonExample(Param a)
*
*  Y como final, el método getInstance, simplemente devolvería el objeto ya 
* instanciado, no llamaría
 al método init(Param a)
*
* Fuente Wikipedia
*
* @author icendrero
*/
public class SingletonExample {
 
  /**
  * Objeto interno que sólo será inicializado una vez
  */
  private static SingletonExample INSTANCE;
 
 
  /**
  * Constructor por defecto.
  */
  private SingletonExample(){}
 
 
  /**
  * Metodo interno que inicializa la instancia única tomando precauciones 
* para evitar instanciación múltiple
  * en aplicaciones multi-hilo. Nunca está de más, vaya.
  * @return
  */
  private static final SingletonExample init(){
        if (INSTANCE == null) {
              synchronized(ParseadorSecciones.class) {
            // En la zona sincronizada sería necesario volver
            // a comprobar que no se ha creado la instancia
            if (INSTANCE == null) {
                INSTANCE = new SingletonExample();
            }
        }
    }
        return INSTANCE;
  }
 
  /**
  * Cada vez que se quiera a acceder al único objeto que hay en memoria, se
  * llamará internamente al método init(). Si no se ha iniciado, se creará una
  * instancia única nueva, si ya está inicializado, devolverá esa instancia.
  * @return
  */
  public static final SingletonExample getInstance(){
        return init();
  }
 
  //El método "clone" es sobreescrito por el siguiente que arroja una excepción:
  public Object clone() throws CloneNotSupportedException {
      throw new CloneNotSupportedException();
  }
 
  /**
  * Metodo main
  */
  public static void main(String[] args) {
        SingletonExample s1 = SingletonExample.getInstance();
        SingletonExample s2 = SingletonExample.getInstance();
        System.out.println("¿Son iguales? - " + s1.equals(s2));
       
  }
}

No hay comentarios:

Publicar un comentario