¿Hay alguna otra forma alternativa de implementar una caja de conmutadores en Java que no sea otra que no se vea bien? Un conjunto de valores estará allí en combinación, de acuerdo con la selección, el método correspondiente debe ser ejecutado.Alternativa a la caja del conmutador en Java
Respuesta
Es de suponer que estás luchando con el requisito de que el caso sea constante. Normalmente, este es un olor a código, pero hay cosas que puedes hacer. Es posible que desee plantear y vincular a otra pregunta que detalla por qué está tratando de cambiar.
Map<String,Object> map = new HasMap<String,Object>();
// ... insert stuff into map
// eg: map.add("something", new MyObject());
String key = "something";
if (map.contains(key)) {
Object o = map.get(key);
}
En el ejemplo anterior, es posible que desee asignar a los manipuladores '', algo así como
interface Handler {
public void doSomething();
}
que a su vez hace que esto se convierta en una búsqueda.
if (map.contains(key)) { map.get(key).doSomething(); }
De nuevo, es un poco olor, así que por favor publique una pregunta que ilustre el razonamiento.
También podría usar Enums si la constancia es un dolor. – Ibrahim
buscando algo como esto. –
¿Por qué contiene y luego obtiene su lectura del mapa dos veces? Comando comment = map.get (clave); if (! = Comando nulo) { ... command.execute(); } –
¿Qué desea hacer? ¿Por qué no es Switch-Case lo suficientemente bueno?
La respuesta rápida es: utilizar if-else
if() {}
else if() {}
...
else if() {}
?
Pero yo no diría que es mejor ...
una serie fea de if,else if,else
?
¿Qué tal un if
(junto con else if
y else
) declaración? Mientras que switch
solo le permitirá cambiar usando igualdad contra enteros o tipos Enum, if
le permite usar cualquier lógica booleana.
char, byte, corto también se puede utilizar en los interruptores. – dogbane
Sí, pero pueden también ser segura (automáticamente) echaron a int –
La refacturación de su código para usar polimorfismo podría eliminar la necesidad de una declaración de cambio. Sin embargo, hay algunos usos legítimos para el cambio, así que depende de su situación.
Si- esto es un conocido refactoring- http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html – RichardOD
Niza enlace. Parece que hay muchos buenos en el catálogo. –
Siempre puede reemplazar un interruptor con if-else if-else if-else if...
, aunque no veo por qué lo desea. Dependiendo del contexto switch
s también a veces puede ser reemplazado por matrices o hashmaps.
Si tiene un montón de declaraciones de interruptor/caja alrededor de su código y que están volviendo loco.
Se podría optar por el Refactoring: Replace conditional with polymorphism.
Digamos que usted tiene una pieza de software que se utiliza para guardar información en diferentes dispositivos: 4 operaciones de persistencia se definen: buscar, guardar, eliminar, actualización, que podría ser implementado por N número de mecanismo de persistencia (archivos planos, red, RDBMS, XML, etc.).
El código tiene que apoyar a todos ellos por lo que en 4 lugares diferentes que tiene la siguiente:
ANTES
class YourProblematicClass {
....
public void fetchData(Object criteria) {
switch (this.persitanceType) {
case FilePersistance:
// open file
// read it
// find the criteria
// build the data
// close it.
break;
case NetWorkPersistance:
// Connect to the server
// Authenticate
// retrieve the data
// build the data
// close connection
break();
case DataBasePersistace:
// Get a jdbc connection
// create the query
// execute the query
// fetch and build data
// close connection
break;
}
return data;
}
Lo mismo para guardar/borrar/actualización
public void saveData(Object data) {
switch (this.persitanceType) {
case FilePersistance:
// open file, go to EOF, write etc.
break;
case NetWorkPersistance:
// Connect to the server
// Authenticate
// etc
break();
case DataBasePersistace:
// Get a jdbc connection, query, execute...
break;
}
}
Y etc.
public void deleteData(Object data) {
switch (this.persitanceType) {
case FilePersistance:
break;
case NetWorkPersistance:
break();
case DataBasePersistace:
break;
}
}
public void updateData(Object data) {
switch (this.persitanceType) {
case FilePersistance:
break;
case NetWorkPersistance:
break();
case DataBasePersistace:
break;
}
}
Usando sentencia switch/case convierte en un problema:
Cada vez que desee añadir un nuevo tipo que tiene que insertar el nuevo interruptor/caja en cada sección.
Muchas veces, algunos tipos son similares, y que no necesitan un interruptor/caso diferente (se puede conectar en cascada ellos)
- Algunos otros que son, y algunas veces difieren ligeramente
- Usted puede aunque tenga que cargar diverso tipo en tiempo de ejecución (como plugins)
Así que la refactorización aquí habría que añadir una interfaz o tipo abstracto y tienen los diferentes tipos implementan esa interfaz y delegar la responsabilidad a ese objeto.
Así que tendría algo como esto:
DESPUÉS
public interface PersistenceManager {
public void fetchData(Object criteria);
public void saveData(Object toSave);
public void deleteData(Object toDelete);
public void updateData(Object toUpdate);
}
y diferentes implementaciones
public class FilePersistence implements PersistanceManager {
public void fetchData(Object criteria) {
// open file
// read it
// find the criteria
// build the data
// close it.
}
public void saveData(Object toSave) {
// open file, go to EOF etc.
}
public void deleteData(Object toDelete){
....
}
public void updateData(Object toUpdate){
....
}
}
Y los otros tipos implementaría acuerdo con su lógica. La red trataría con sockets, y streams, DB trataría con JDBC, ResultSets etc. XML con node etc.etc.
public class NetworkPersistence implements PersistanceManager {
public void fetchData(Object criteria) {
// Socket stuff
}
public void saveData(Object toSave) {
// Socket stuff
}
public void deleteData(Object toDelete){
// Socket stuff
}
public void updateData(Object toUpdate){
// Socket stuff
}
}
public class DataBasePersistence implements PersistanceManager {
public void fetchData(Object criteria) {
// JDBC stuff
}
public void saveData(Object toSave) {
// JDBC stuff
}
public void deleteData(Object toDelete){
// JDBC stuff
}
public void updateData(Object toUpdate){
// JDBC stuff
}
}
Y finalmente solo tiene que delegar las invocaciones.
después:
public YouProblematicClass { // not longer that problematic
PersistamceManager persistance = // initialize with the right one.
public void fetchData(Object criteria) {
// remove the switch and replace it with:
this.persistance.fetchData(criteria);
}
public void saveData(Object toSave) {
// switch removed
this.persistance.saveData( toSave);
}
public void deleteData(Object toDelete){
this.persistance.deleteData(toDelete);
}
public void updateData(Object toUpdate){
this.persistance.updateData(toUpdate);
}
}
Por lo tanto, sólo hay que crear la instancia correcta para el gestor de persistencia de acuerdo con el tipo de una sola vez. Entonces todas las invocaciones se resuelven por polimorfismo. Esa es una de las características clave de Object Oriented Technology.
Si decide que necesita otro administrador de persistencia, solo cree la nueva implementación y asigne la clase.
public WavePersistance implements PersistanceManager {
public void fetchData(Object criteria) {
// ....
}
public void saveData(Object toSave) {
// ....
}
public void deleteData(Object toDelete){
// ....
}
public void updateData(Object toUpdate){
// ....
}
}
Muy buena respuesta! – mac
o uno podría imaginar una especie de caja de conmutación dinámica:
public interface Task<T>
{
public void doSomething(T context);
}
public Class SwitchCase<T>
{
Map<Integer,Task<T>> tasks;
Task<T> defaultTask;
public void choose(int choice, T context)
{
Task<T> t= this.tasks.get(choice);
if(t!=null) { t.doSomething(context); return;}
if(defaultTask!=null) { defaultTask.doSomething(context);}
}
}
supongo "código limpio" tiene un capítulo agradable según switch/case vs if/else.
Además Creo que tiene sentido para decidir si se puede reducir el "ruido" y hacer el código más limpio mediante el uso de caja de conmutación, polimorfismo o incluso un buen ol' if/else. El número de casos juega un papel importante aquí, supongo.
Si las cadenas son estáticos, se puede hacer una enumeración. y enciéndalo.
puedo enviar un caso típico de cómo he sustituido caso conmutador con enumeración.
antes refactor tengo enumeración PatternTypes
:
public enum PatternTypes {
ALPHA_CHAR, ALPHANUMERIC_CHAR, ADDITIONAL_CHAR, UNICODE_BMP_CHARS
}
y función:
private static final String ALPHA_CHAR = "[a-zA-Z]+";
private static final String ALPHANUMERIC_CHAR = "[a-zA-Z0-9\\_]+";
private static final String ADDITIONAL_CHAR = "[a-zA-Z0-9\\_\\-\\,\\.\\s\\!\\#\\$\\&\\(\\)\\*\\+\\;\\:\\=\\?\\@\\|\\[\\]\\{\\}\\~]+";
private static final String UNICODE_BMP_CHARS = "[a-zA-Z0-9\\_\\-\\,\\.\\s\\!\\#\\$\\&\\(\\)\\*\\+\\;\\:\\=\\?\\@\\|\\[\\]\\{\\}\\~\u00A0-\uD7FF\uF900-\uFFFD]+";
/*
* Match given classAbbr with given RegEx pattern
*/
private void checkInvalidClassAbbr(String classAbbr,
PatternTypes classAbbrPattern) {
switch (classAbbrPattern) {
case ALPHA_CHAR:
checkUnmatched(classAbbr, ALPHA_CHAR, CLASS_ABBR_VAR_NAME);
break;
case ALPHANUMERIC_CHAR:
checkUnmatched(classAbbr, ALPHANUMERIC_CHAR, CLASS_ABBR_VAR_NAME);
break;
case ADDITIONAL_CHAR:
throw new MalFormedDNException("Not support Pattern Type:"
+ classAbbrPattern);
case UNICODE_BMP_CHARS:
throw new MalFormedDNException("Not support Pattern Type:"
+ classAbbrPattern);
}
}
Después de perfeccionar por PatternTypes
modificar para:
public enum PatternTypes {
/**
* RegEx patterns divided by restriction level
*/
ALPHA_CHAR("[a-zA-Z]+"),
ALPHANUMERIC_CHAR("[a-zA-Z0-9\\_]+"),
ADDITIONAL_CHAR("[a-zA-Z0-9\\_\\-\\,\\.\\s\\!\\#\\$\\&\\(\\)\\*\\+\\;\\:\\=\\?\\@\\|\\[\\]\\{\\}\\~]+"),
UNICODE_BMP_CHARS("[a-zA-Z0-9\\_\\-\\,\\.\\s\\!\\#\\$\\&\\(\\)\\*\\+\\;\\:\\=\\?\\@\\|\\[\\]\\{\\}\\~\u00A0-\uD7FF\uF900-\uFFFD]+");
public String getPatternContent() {
return patternContent;
}
private String patternContent;
PatternTypes(String patternContent) {
this.patternContent = patternContent;
}
}
y función simplificar a:
/*
* Match given classAbbr with given RegEx pattern
*/
private void checkInvalidClassAbbr(String classAbbr, PatternTypes classAbbrPattern) {
if (PatternTypes.ADDITIONAL_CHAR.equals(classAbbrPattern) || PatternTypes.UNICODE_BMP_CHARS.equals(classAbbrPattern)){
throw new MalFormedDNException("RegEx pattern:" + classAbbrPattern.name() + "is not allowed for Class Abbr");
}
checkUnmatched(classAbbr, classAbbrPattern.getPatternContent(), CLASS_ABBR_VAR_NAME);
}
Hashmap no se considera compatible con la memoria, por lo que puede utilizar Enum para este fin.
Ejemplo:
class EnumExample4{
enum Season{
WINTER(5), SPRING(10), SUMMER(15), FALL(20);
private int value;
private Season(int value){
this.value=value;
}
}
public static void main(String args[]){
System.out.println(Season.WINTER.value); //This gives you 5
}}
Esto le sve de escribir Interruptor de casos o si las declaraciones.
¿Puede dar alguna referencia para respaldar el reclamo * Hashmap no se considera compatible con la memoria *? Si puede, edite su respuesta para vincularla allí. – derM
- 1. Eclipse: autocompletado de Java Enum de la caja del conmutador
- 2. Obtenga un comportamiento de conmutador/caja en Perl 5
- 3. Uso de representaciones de cadena de valores enum en la caja del conmutador
- 4. Contexto del lienzo del conmutador
- 5. alternativa a la sentencia if en Java
- 6. alternativa a File.Exists() en Java
- 7. Alternativa a la clase observable de Java?
- 8. ¿Alternativa moderna a la biblioteca Java XStream?
- 9. Alternativa a las Preferencias en Java
- 10. alternativa a servicewrapper para java?
- 11. Conmutador Java: declaración de variable y alcance
- 12. Thread.Sleep alternativa en Java
- 13. caja del interruptor con etiqueta de visualización
- 14. 0 en la caja del interruptor?
- 15. referencia enum en la caja del interruptor
- 16. ¿Múltiples condiciones en la caja del interruptor?
- 17. Vista del conmutador ActivityGroup con animación
- 18. caja del interruptor en XSL
- 19. ¿Por qué el compilador de C# requiere la declaración de interrupción en la construcción del conmutador?
- 20. Android Multi estado del conmutador de
- 21. Construir un conmutador basado en la matriz
- 22. Alternativa de multihilo en Java
- 23. Cómo hacer que la declaración del conmutador C# use IgnoreCase
- 24. Alternativa de Java a Windows Workflow Foundation
- 25. ¿Existe una alternativa no Java a OSGi?
- 26. ¿Alternativa a la gitosis?
- 27. Conmutador retrocompatible
- 28. ¿Funciona el conmutador de casos así?
- 29. La caja del interruptor JS no funciona
- 30. ¿Cuál es la alternativa de Java principal a ASP.NET/PHP
¿Qué quieres decir cuando dices 'Un conjunto de valores estará allí en combo'? – Alterlife
ya formuladas homóloga pregunta http://stackoverflow.com/questions/126409/ways-to-eliminate-switch-in-code –
@cdb: Entonces ¿por qué lo preguntas de nuevo? ¿Qué no te dijeron las respuestas anteriores? –