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 se pueden enviar a estos dispositivos a través de transmisiones de radio. Esto solo se puede hacer mediante texto. dentro de las bibliotecas del sistema, tengo un hilo que maneja los comandos que se ven 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 mirar, doloroso de depurar y alucinante de entender en unos meses.
Respuestas:
usando el patrón de comando :
luego construye un
Map<String,Command>
objeto y complétalo conCommand
instancias:entonces puede reemplazar su cadena if / else if con:
EDITAR
también puede agregar comandos especiales como
UnknownCommand
oNullCommand
, pero necesita unCommandMap
que maneje estos casos de esquina para minimizar los controles del cliente.fuente
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.
Por supuesto, puede pasar parámetros a doCommand o tener tipos de retorno.
Es posible que esta solución no sea realmente adecuada si las implementaciones de doCommand no "encajan" realmente en el tipo enum, que es, como es habitual cuando hay que hacer una compensación, un poco difuso.
fuente
Tener una enumeración de comandos:
Si tiene más de unos pocos comandos, considere usar el patrón Command, como se respondió en otro lugar (aunque puede retener 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 para ver un ejemplo.
fuente
La implementación de una interfaz como la demuestra dfa simple y llanamente es limpia y elegante (y es compatible "oficialmente"). Para esto está destinado el concepto de interfaz.
En C #, podríamos usar delegados para programadores a los que les gusta usar punteros de función en c, pero la técnica de DFA es la forma de usar.
También podrías tener una matriz
Entonces podrías ejecutar un comando por índice
Plagio de DFA, pero con una clase base abstracta en lugar de una interfaz. Observe la cmdKey que se usaría más tarde. Por experiencia, me doy cuenta de que con frecuencia un comando de equipo también tiene subcomandos.
Construye tus mandamientos así,
Luego, podría extender HashMap o HashTable genérico proporcionando una función de succión de par clave-valor:
Luego construye tu almacén de comandos:
Ahora puedes enviar controles de forma objetiva
fuente
Bueno, sugiero crear objetos de comando y ponerlos en un mapa hash usando la Cadena como clave.
fuente
Incluso si creo que el enfoque del patrón de comando está más orientado a las mejores prácticas y se puede mantener a largo plazo, aquí hay una opción de una línea para usted:
org.apache.commons.beanutils.MethodUtils.invokeMethod (esto, "doCommand" + valor, nulo);
fuente
Normalmente trato de resolverlo de esa manera:
esto tiene muchas ventajas:
1) no es posible agregar una enumeración sin implementar exec. para que no te pierdas una A.
2) ni siquiera tendrá que agregarlo a ningún mapa de comando, por lo que no hay código repetitivo para construir el mapa. solo el método abstracto y sus implementaciones. (que podría decirse que también es repetitivo, pero no se acortará ...)
3) Ahorrará cualquier ciclo de CPU desperdiciado revisando una larga lista de if's o calculando hashCodes y haciendo búsquedas.
editar: si no tiene enumeraciones sino cadenas como fuente, solo use
Command.valueOf(mystr).exec()
para llamar al método exec. tenga en cuenta que debe usar el modificador público en execif al que desea llamar desde otro paquete.fuente
Probablemente sea mejor que utilice un mapa de comandos.
Pero si tienes un conjunto de estos para manejar, terminas con un montón de mapas dando vueltas. Entonces vale la pena intentarlo con Enums.
Puede hacerlo con un Enum sin usar modificadores (probablemente no necesite los getters en el ejemplo), si agrega un método al Enum para resolver el "valor". Entonces puedes simplemente hacer:
Actualización: se agregó un mapa estático para evitar la iteración en cada llamada. Desvergonzadamente pellizcado por esta respuesta .
fuente
La respuesta proporcionada por @dfa es la mejor solución, en mi opinión.
Solo proporciono algunos fragmentos en caso de que esté utilizando Java 8 y quiera usar Lambdas!
Comando sin parámetros:
(podría usar un Runnable en lugar de Command, pero no lo considero semánticamente correcto):
Comando con un parámetro:
En caso de que espere un parámetro, puede usar
java.util.function.Consumer
:En el ejemplo anterior,
doSomethingX
hay un método presente enmyObj
la clase de que toma cualquier Objeto (nombradoparam
en este ejemplo) como argumento.fuente
si tiene varias declaraciones "if" imbricadas, entonces este es un patrón para usar un motor de reglas . Consulte, por ejemplo, JBOSS Drools .
fuente
Simplemente use un HashMap, como se describe aquí:
fuente
si fuera posible tener una serie de procedimientos (lo que llamó comandos) sería útil ...
pero podrías escribir un programa para escribir tu código. Todo es muy sistemático if (value = 'A') commandA (); más si (........................ etc
fuente
No estoy seguro de si tiene alguna superposición entre el comportamiento de sus diversos comandos, pero es posible que también desee echar un vistazo al patrón de Cadena de responsabilidad que podría proporcionar más flexibilidad al permitir que múltiples comandos manejen algunos valores de entrada.
fuente
El patrón de comando es el camino a seguir. Aquí hay un ejemplo usando java 8:
1. Defina la interfaz:
2. Implemente la interfaz con cada una de las extensiones:
y
y así .....
3. Defina el cliente:
4. Y este es el resultado de la muestra:
fuente
Si hace muchas cosas, entonces habrá mucho código, realmente no puedes alejarte de eso. Simplemente hágalo fácil de seguir, asigne nombres muy significativos a las variables, los comentarios también pueden ayudar ...
fuente