Java 中 if 语句的长列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1199646/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:49:56  来源:igfitidea点击:

Long list of if statements in Java

javadesign-patternscommand-pattern

提问by Steve

Sorry I can't find a question answering this, I'm almost certain someone else has raised it before.

抱歉,我找不到可以回答这个问题的问题,我几乎可以肯定其他人之前已经提出过这个问题。

My problem is that I'm writing some system libraries to run embedded devices. I have commands which can be sent to these devices over radio broadcasts. This can only be done by text. inside the system libraries I have a thread which handles the commands which looks like this

我的问题是我正在编写一些系统库来运行嵌入式设备。我有可以通过无线电广播发送到这些设备的命令。这只能通过文本来完成。在系统库中,我有一个线程来处理看起来像这样的命令

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

The problem is that there are a lot of commands to it will quickly spiral to something out of control. Horrible to look out, painful to debug and mind boggling to understand in a few months time.

问题是它有很多命令会很快变得无法控制。看起来很可怕,调试起来很痛苦,几个月后很难理解。

采纳答案by dfa

using Command pattern:

使用命令模式

public interface Command {
     void exec();
}

public class CommandA() implements Command {

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

// etc etc

then build a Map<String,Command>object and populate it with Commandinstances:

然后构建一个Map<String,Command>对象并用Command实例填充它:

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

then you can replace your if/else ifchain with:

那么你可以用以下方法替换你的if/ else if链:

commandMap.get(value).exec();

EDIT

编辑

you can also add special commands such as UnknownCommandor NullCommand, but you need a CommandMapthat handles these corner cases in order to minimize client's checks.

您还可以添加特殊命令,例如UnknownCommandNullCommand,但您需要一个CommandMap处理这些极端情况的命令,以最大限度地减少客户的检查。

回答by Mark

If it does a lot of things, then there will be a lot of code, you cant really get away from that. Just make it easy to follow, give the variables very meaningful names, comments can help too...

如果它做了很多事情,那么就会有很多代码,你真的无法摆脱它。只是让它易于理解,给变量赋予非常有意义的名称,注释也可以提供帮助......

回答by keuleJ

Well I suggest to create command objects and put them into a hashmap using the String as Key.

好吧,我建议创建命令对象并将它们放入使用字符串作为键的哈希映射中。

回答by ars

Just use a HashMap, as described here:

只需使用 HashMap,如下所述:

回答by JeeBee

Have an enum of commands:

有一个命令枚举:

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;
}

If you have more than a few commands, look into using the Command pattern, as answered elsewhere (although you can retain the enum and embed the call to the implementing class within the enum, instead of using a HashMap). Please see Andreas or jens' answer to this question for an example.

如果您有多个命令,请考虑使用 Command 模式,正如在别处回答的那样(尽管您可以保留枚举并将调用嵌入枚举中的实现类,而不是使用 HashMap)。请参阅 Andreas 或 jens 对此问题的回答以获取示例。

回答by user147042

if it was possible to have an array of procedures(what you called commands) that'd be useful..

如果有可能有一组有用的过程(你称之为命令)。

but you could write a program to write your code. It's all very systematic if(value='A') commandA(); else if(........................ e.t.c.

但是你可以编写一个程序来编写你的代码。都是很系统的 if(value='A') commandA(); 否则如果(………………等

回答by svachon

Even if I believe the command pattern approach is more in toward best pratices and maintainable in the long run, here's a one liner option for you:

即使我相信命令模式方法更倾向于最佳实践并且从长远来看可维护,这里有一个单行选项供您选择:

org.apache.commons.beanutils.MethodUtils.invokeMethod(this,"doCommand"+value,null);

org.apache.commons.beanutils.MethodUtils.invokeMethod(this,"doCommand"+value,null);

回答by Pierre

if you have multiple imbricated 'if' statements, then this is a pattern for using a rule engine. See, for example JBOSS Drools.

如果您有多个复杂的“if”语句,那么这是使用规则引擎的一种模式。参见,例如JBOSS Drools

回答by Andreas Petersson

i usually try to solve it that way:

我通常尝试以这种方式解决它:

public enum Command {

A {void exec() {
     doCommandA();
}},

B {void exec() {
    doCommandB();
}};

abstract void exec();
 }

this has many advantages:

这有很多优点:

1) it is not possible to add an enum without implementing exec. so you won't miss an A.

1) 不执行 exec 就不可能添加枚举。所以你不会错过A。

2) you will not even have to add it to any command map, so no boilerplate code for building the map. just the abstract method and its implementations. (which is arguably also boilerplate, but it won't get any shorter..)

2)您甚至不必将其添加到任何命令映射中,因此没有用于构建映射的样板代码。只是抽象方法及其实现。(这可以说也是样板文件,但它不会变得更短..)

3) you will save any wasted cpu cycles by going through a long list of if's or calculating hashCodes and doing lookups.

3) 通过查看一长串 if 或计算 hashCode 并进行查找,您将节省任何浪费的 CPU 周期。

edit: if you don't have enums but strings as source, just use Command.valueOf(mystr).exec()to call the exec method. note that you must use the public modifier on execif you want to call it from another package.

编辑:如果您没有枚举但字符串作为源,只需使用Command.valueOf(mystr).exec()调用 exec 方法。请注意,如果要从另一个包调用它,则必须在 execif 上使用 public 修饰符。

回答by jens

My suggestion would be a kind of lightweight combination of enum and Command object. This is an idiom recommended by Joshua Bloch in Item 30 of Effective Java.

我的建议是 enum 和 Command 对象的一种轻量级组合。这是 Joshua Bloch 在 Effective Java 的第 30 条中推荐的习语。

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();
}

Of course you could pass parameters to doCommand or have return types.

当然,您可以将参数传递给 doCommand 或具有返回类型。

This solution might be not really suitable if the implementations of doCommand does not really "fit" to the enum type, which is - as usual when you have to make a tradeoff - a bit fuzzy.

如果 doCommand 的实现并不真正“适合”枚举类型,则此解决方案可能并不真正适合,这 - 像往常一样,当您必须进行权衡时 - 有点模糊。