Larga lista de declaraciones if en Java

Resuelto Steve asked hace 15 años • 15 respuestas

Lo siento, no puedo encontrar una pregunta que responda a esto, estoy casi seguro de que alguien más la ha planteado antes.

Mi problema es que estoy escribiendo algunas bibliotecas del sistema para ejecutar dispositivos integrados. Tengo comandos que pueden enviarse a estos dispositivos a través de transmisiones de radio. Esto sólo se puede hacer por mensaje de texto. Dentro de las bibliotecas del sistema tengo un hilo que maneja los comandos que se ve así

if (value.equals("A")) { doCommandA() }
else if (value.equals("B")) { doCommandB() } 
else if etc. 

El problema es que hay muchos comandos que rápidamente se convertirán en algo fuera de control. Horrible de ver, doloroso de depurar y alucinante de entender en unos meses.

Steve avatar Jul 29 '09 18:07 Steve
Aceptado

usando el patrón de comando :

public interface Command {
     void exec();
}

public class CommandA() implements Command {

     void exec() {
          // ... 
     }
}

// etc etc

luego construye un Map<String,Command>objeto y llénalo con Commandinstancias:

commandMap.put("A", new CommandA());
commandMap.put("B", new CommandB());

entonces puedes reemplazar tu cadena if / else if con:

commandMap.get(value).exec();

EDITAR

También puede agregar comandos especiales como UnknownCommando NullCommand, pero necesita un comando CommandMapque maneje estos casos extremos para minimizar las comprobaciones del cliente.

dfa avatar Jul 29 '2009 11:07 dfa

Mi sugerencia sería una especie de combinación ligera de enumeración y objeto Command. Este es un modismo recomendado por Joshua Bloch en el artículo 30 de Effective Java.

public enum Command{
  A{public void doCommand(){
      // Implementation for A
    }
  },
  B{public void doCommand(){
      // Implementation for B
    }
  },
  C{public void doCommand(){
      // Implementation for C
    }
  };
  public abstract void doCommand();
}

Por supuesto, puedes pasar parámetros a doCommand o tener tipos de retorno.

Esta solución podría no ser realmente adecuada si las implementaciones de doCommand realmente no "se ajustan" al tipo de enumeración, lo cual es, como es habitual cuando hay que hacer una compensación, un poco confuso.

jens avatar Jul 29 '2009 12:07 jens

Tener una enumeración de comandos:

public enum Commands { A, B, C; }
...

Command command = Commands.valueOf(value);

switch (command) {
    case A: doCommandA(); break;
    case B: doCommandB(); break;
    case C: doCommandC(); break;
}

Si tiene más de unos pocos comandos, considere usar el patrón Comando, como se respondió en otra parte (aunque puede conservar la enumeración e incrustar la llamada a la clase de implementación dentro de la enumeración, en lugar de usar un HashMap). Consulte la respuesta de Andreas o Jens a esta pregunta como ejemplo.

JeeBee avatar Jul 29 '2009 11:07 JeeBee