El Blog de Ana Buigues » Enum http://anabuigues.com Wed, 07 Dec 2011 16:07:47 +0000 es-ES hourly 1 http://wordpress.org/?v=3.4 Definir una Singleton en Java mediante un enum http://anabuigues.com/2010/02/15/definir-una-singleton-en-java-mediante-un-enum/ http://anabuigues.com/2010/02/15/definir-una-singleton-en-java-mediante-un-enum/#comments Mon, 15 Feb 2010 19:10:47 +0000 Ana Buigues http://anabuigues.com/?p=348 El otro día leyendo el libro de Effective Java de Joshua Bloch, me encontré con una nueva forma de declarar el patrón de diseño Singleton.

Una singleton es simplemente una clase que es instanciada exactamente una vez. Antes de Java 1.5 había dos formas de implementar una singleton, ambas se basan en un contructor privado y en proporcionar un miembro público y estático que da acceso a una sola instancia. A partir de Java 1.5 aparece una tercera opción para implementar una singleton, simplemente mediante un tipo enumerado con un único elemento:

public enum Singleton {
    INSTANCE;
    public String nombre(){
           return this.getClass().getName();
    }
}

Este enfoque es funcionamente equivalente a los dos anteriores, excepto porque es más conciso y ofrece una rigurosa garantía contra múltiples instanciaciones, ya que con los métodos anteriores podíamos invocar al constructor privado mediante reflexión y obtener más de una instancia. En el siguiente ejemplo, creamos por reflexión dos enums:

public static void main(String[] args) {
  Constructor<Singleton> ctor = Singleton.class.getDeclaredConstructor(String.class, int.class);
  Method acqMethod = ctor.getClass().getDeclaredMethod("acquireConstructorAccessor");
  acqMethod.setAccessible(true);
  acqMethod.invoke(ctor);
  Field accessorField = ctor.getClass().getDeclaredField("constructorAccessor");
  accessorField.setAccessible(true);
  Object accessor = accessorField.get(ctor);
  Method newInstanceMethod = accessor.getClass().getMethod("newInstance", Object[].class);
  newInstanceMethod.setAccessible(true);
  Singleton singleton1 = (Singleton) newInstanceMethod.invoke(accessor, new Object[]{new Object[]{"hey", 1}});
  Singleton singleton2 = (Singleton) newInstanceMethod.invoke(accessor, new Object[]{new Object[]{"hey", 1}});
  if(singleton1 == singleton2){
  	System.out.println("son iguales los objetos");
  }else{
  	System.out.println("no son iguales los objetos");
  }
  if(singleton1.INSTANCE == singleton2.INSTANCE){
	System.out.println("son iguales las instancias");
  }else{
	System.out.println("no son iguales las instancias");
  }
}

Como resultado de ejecutar el código, obtenemos dos objetos distintos, pero las instancias de su interior son la misma y por tanto mediante reflexión no hemos roto la singleton.

Además dado que los enumerados implementan la interfaz serializable no necesitamos hacer nada adicional para serializar este objeto.

Según Joshua Bloch es la mejor manera de instanciar una singleton.

]]>
http://anabuigues.com/2010/02/15/definir-una-singleton-en-java-mediante-un-enum/feed/ 6