java - parameter - Cómo eliminar una cadena grande if-else-if
ftl if null (6)
Algunas opciones / ideas:
- Déjelo como está : no está fundamentalmente roto, y es razonablemente claro y fácil de mantener
- Use una instrucción de cambio (si está usando Java 7) - no estoy seguro si esto le gana mucho
- Cree un HashMap de String a FunctionObjects donde los objetos de función implementan el comportamiento requerido como un método. Entonces su código de llamada es simplemente:
hashMap.get(name).doSomething();
- Divídalo en una jerarquía de llamadas a funciones subgrupando las cadenas. Puede hacer esto tomando cada letra, por lo que una rama maneja todos los nombres que comienzan con ''a'', etc.
- Refactorice para que no pase el nombre como una Cadena, sino que pase un objeto con nombre. Entonces solo puedes hacer
namedObject.doSomething()
Posible duplicado:
Larga lista de declaraciones if en Java
Me asignaron la tarea de trabajar con algún código, y hay una cadena gigante if-else-if (100+ else-ifs) que verifica cadenas.
¿Cuáles son algunas buenas técnicas para actualizar este código en cuanto a dónde la cadena if-else-if puede reducirse a algo mucho más manejable?
La cadena se ve algo como esto:
if(name.equals("abc")){
do something
} else if(name.equals("xyz")){
do something different
} else if(name.equals("mno")){
do something different
} ......
.....
else{
error
}
Como dijo Matt Ball en su comentario, puedes usar un patrón de comando. Defina una colección de clases ejecutables:
Runnable task1 = new Runnable() {
public void run() { /* do something */ }
};
Runnable task2 = // etc.
Luego puedes usar un mapa de tus llaves para ejecutar:
Map<String,Runnable> taskMap = new HashMap<String,Runnable>();
taskMap.put("abc", task1);
taskMap.put("xyz", task2);
// etc.
Finalmente, reemplace la cadena if-else con:
Runnable task = taskMap.get(name);
if (task != null) {
task.run();
} else {
// default else action from your original chain
}
Con Enums, puedes tener un método por instancia.
public enum ActionEnum {
ABC {
@Override
void doSomething() {
System.out.println("Doing something for ABC");
}
},
XYZ {
@Override
void doSomething() {
System.out.println("Doing something for XYZ");
}
};
abstract void doSomething();
}
public class MyActionClass {
public void myMethod(String name) {
ActionEnum.valueOf("ABC").doSomething();
}
}
Todavía es un poco desordenado (gran enumeración con más de 100 entradas, incluso todo lo que hace es enviar), pero puede evitar el código de inicialización de HashMap (más de 100 es también desordenado, en mi opinión).
Y aún otra opción (para propósitos de documentación) sería la reflexión:
public interface Action {
void doSomething();
}
public class ABCAction implements Action {
@Override
public void doSomething() {
System.out.println("Doing something for ABC");
}
}
public class MyActionClass {
void doSomethingWithReflection(String name) {
try {
Class<? extends Action> actionClass = Class.
forName("actpck."+ name + "Action").asSubclass(Action.class);
Action a = actionClass.newInstance();
a.doSomething();
} catch (Exception e) {
// TODO Catch exceptions individually and do something useful.
e.printStackTrace();
}
}
}
Cada enfoque tiene sus ventajas y desventajas:
- HashMap = Rápido + Un poco desordenado (código de "configuración" con cientos de entradas)
- Enum = Rápido + Un poco desordenado 2 (archivo enorme).
- Reflexión = Más lento + propenso a error de tiempo de ejecución, pero proporciona una separación limpia sin recurrir a HashMap grande e incómodo.
Este es un popular Anti-Pattern de Arrow y Jeff analiza algunos enfoques para manejar esto muy bien en su publicación aquí .
Puede extraer el código en cada rama a un método separado, luego convertir los métodos en implementaciones de una interfaz base común (llamémoslo Handler
). Después de eso, puede rellenar un Map<String, Handler>
y simplemente buscar y ejecutar el controlador correcto para la cadena dada.
Desafortunadamente, la implementación de más de 100 subclases para la interfaz requiere bastante código repetitivo, pero en la actualidad no existe una forma más sencilla en Java para lograrlo. Implementar los casos como elementos de un Enum
puede ayudar un poco, aquí hay un ejemplo . La solución ideal sería utilizar cierres / lambdas, pero desgraciadamente, debemos esperar hasta Java 8 para eso ...
puede utilizar la instrucción de cambio, pero las instrucciones de cambio con casos de cadena se han implementado en Java SE 7
La mejor solución es usar el patrón de comando.