sirve que patron para method enum java enums factory

patron - para que sirve enum en java



Usando Enum para Factory en Java, ¿una mejor práctica? (4)

El segundo es mucho más limpio: no necesita ningún bloque de interruptor largo, y tiene 0 riesgos de olvidar uno de los valores de enumeración como el primero.

Sin embargo, no siempre es posible usarlo, ya que la enumeración podría ser una enumeración genérica ( Month , por ejemplo), que no debería estar acoplada a la fábrica de acciones.

Java nos permite incrustar datos y comportamientos en Enum. No quiero implementar una fábrica directamente en un Enum, porque creo que este no es su papel.

Pero puedo poner una referencia de clase en la enumeración y construir un objeto en una fábrica externa. En comparación con un patrón de fábrica tradicional, ¿cuál es la mejor implementación para usted? ¿Qué solución es mejor usar en qué caso?

Ahora, el código.

Función utilizada en ambas soluciones para construir objetos. Útil para implementar el patrón de peso de la mosca con un mapa si es necesario.

private Action getAction(Class<? extends Action> actionClazz) { // logger + error handling return actionClazz.newInstance(); }

1) Con una fábrica tradicional:

public enum ActionEnum { LOAD_DATA, LOAD_CONFIG; } public Action getAction(ActionEnum action) { switch (action) { case LOAD_CONFIG: return getAction(ActionLoadConfig.class); case LOAD_DATA: return getAction(ActionLoadData.class); } }

2) Con la fábrica de estilo Enum:

public enum ActionEnum { LOAD_DATA(ActionLoadConfig.class), LOAD_CONFIG(ActionLoadData.class); public ActionEnum(Class<? extends Action> clazz){...} public Class<? extends Action> getClazz() {return this.clazz} } public Action getAction(ActionEnum action) { return getAction(action.getClazz()); }


Esto funciona para mí:

enum ActionEnum { LOAD_DATA { @Override public ActionLoadData getInstance() { return new ActionLoadData (); } }, LOAD_CONFIG { @Override public ActionLoadConfig getInstance() { return new ActionLoadConfig(); } }; public abstract ILightBulb getInstance(); } class ActionFactory { public Action getAction(ActionEnum action) { return action.getInstance(); } }


La IMO que llama a newInstance() debe evitarse si es posible, ya que newInstance() algunas de las protecciones de tiempo de compilación dadas por java (lee su javadoc) e introduce nuevas Exception a manejar.

Aquí hay una solución similar a la que Sergey proporcionó , solo un poco más concisa gracias a interfaces funcionales y referencias de métodos.

public enum ActionEnum { LOAD_DATA(ActionLoadData::new), LOAD_CONFIG(ActionLoadConfig::new) private Supplier<Action> instantiator; public Action getInstance() { return instantiator.get(); } ActionEnum(Supplier<Action> instantiator) { this.instantiator = instantiator; } } public Action getAction(ActionEnum action) { return action.getInstance(); }


Para desacoplar aún más:

static final EnumMap<ActionEnum, Class<? extends Action>> enumToClass = new EnumMap<>(); static { enumToClass.put(ActionEnum.LOAD_DATA, ActionLoadData.class); etc... } public Action getAction(ActionEnum action) { return getAction(enumToClass.get(action)); }

EnumMap es muy rápido, así que no te preocupes.