Los enums siguen molando

Escribí hace tiempo una entrada en la que hacía público mi amor hacia los enums. A día de hoy creo que no los uso lo suficiente y voy poco a poco aprendiendo cosas nuevas. Con todo esto, no me ha quedado otra que escribir una segunda parte: Los enums siguen molando.

Una característica por la que los enums son conocidos y se suelen usar es la imposibilidad de invocar al constructor (ni con reflection) por lo que son buenos candidatos para utilizarlos como singletons.

En Effective Java, el autor define los métodos constant-specific methods como las implementaciones de un método abstracto en el enum. Esto permite asociar comportamiento a los elementos que se definen. Y obliga a definir el comportamiento por cada elemento nuevo.

public enum PiecesToClean {
    LIVING_ROOM {
        @Override public void clean() {
            System.out.println("Cleaning the living room");
        }
    },
    KITCHEN {
        @Override public void clean() {
            System.out.println("Cleaning the kitchen");
        }
    },
    BATH_ROOM {
        @Override public void clean() {
            System.out.println("Cleaning the bath room");
        }
    };

    public abstract void clean();
}

Por otra parte, Joshua Bloch propone el strategy enum pattern en el que los diferentes comportamientos de los enums son definidos en el constructor de cada elemento. De esta forma, el compilador nos obliga a definir el comportamiento para cada constante pero además contamos con la flexibilidad del patrón strategy a la hora de escribir diferentes comportamientos reutilizables para cada enum.

public enum PiecesToClean {
    LIVING_ROOM(CleaningStrategy.SHALLOW),
    KITCHEN(CleaningStrategy.DEEP),
    BATH_ROOM(CleaningStrategy.DEEP);

    private final CleaningStrategy cleaningStrategy;

    PiecesToClean(CleaningStrategy cleaningStrategy) {
        this.cleaningStrategy = cleaningStrategy;
    }

    public void clean() {
        cleaningStrategy.clean();
    }
}
public enum CleaningStrategy {
    SHALLOW() {
        @Override public void clean() {
            System.out.println("Cleaning fast");
        }
    },
    DEEP() {
        @Override public void clean() {
            System.out.println("Cleaning with love");
        }
    };

    public abstract void clean();
}

En el mismo capítulo también se propone lanzar una excepción para el caso por defecto en los bloques switch sobre el enum ya que el autor pone en evidencia el peligro de los enums en bloques switch teniendo en cuenta que se puede añadir un elemento nuevo pero olvidar añadir en los bloques switch (diseminados por todo el código) el caso para esa constante, por lo que aplicará el caso por defecto.

switch (piece) {
   case LIVING_ROOM:
      piece.clean(); break;
   case KITCHEN:
      piece.clean(); break;
   case BATH_ROOM:
      piece.clean(); break;
   default:
      throw new IllegalArgumentException("You should have defined this use case");
}

Mi compi Jorge me enseñó el otro día cómo utilizaba un enum para implementar un Predicate de Java 8. Cada elemento del enum es una regla de negocio y cada uno implementa test() para determinar si se cumple la regla.

public enum BusinessRule implements Predicate {
    RULE_1() {
        @Override public boolean test(DomainObjectUnderRules domainObjectUnderRules) {
            // logic to test rule 1
        }
    },
    RULE_2 {
        @Override public boolean test(DomainObjectUnderRules domainObjectUnderRules) {
            // logic to test rule 2
        }
    };
}

A parte de impresionarme esta forma de usar enums entendí que Java 8 está facilitando mucho el uso de los enumerados, sobre todo, en los casos en los que el enum recibe una lambda en el constructor.

Para terminar, en el libro se recuerda que en Java 7 se introdujo EnumMap que es una implementación de mapas especialmente desarrollada para enums, muy compacta y muy eficiente y cuyo uso no es muy extendido.

 

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s