【问题标题】:alternative to if statement in javajava中if语句的替代方法
【发布时间】:2010-12-09 22:29:37
【问题描述】:

我很想看到常规 if 语句的任何替代方法,例如

if(x)
     do a;
if(y)
     do b;
if(z)
    do c;

所以你看到所有的 if 语句都是单独的,没有 else 条件。请注意,X Y Z 是完全独立的条件,因此 switch 不适合。

【问题讨论】:

  • 虽然好奇可能很幽默......我为什么要替代 if,尤其是当条件是该开关不适合时?好像 Java 还不够臃肿……
  • 要么您尝试做的事情很愚蠢(如果很棒!),或者您需要提供更多信息。我可以想象这样一种情况,可以使用消息传递模式或其他有趣的东西来处理这样的代码(前提是你的情况不像你解释的那么简单)。
  • 您希望这个替代方案提供的代码不能提供什么? (更少的字符,更多的可读性?)
  • @Hellnar:有额外的知识有价值,还有晦涩难懂的代码高尔夫垃圾。
  • 数量够多,if 语句有毒

标签: java if-statement


【解决方案1】:

这是最简单、可读但有效的解决方案。我会很惊讶在这里看到有效的替代方案。

编辑

您可以尝试多次应用提取方法

doAIfX();
doBIfY();
doCifZ();

其中方法定义为:

void doAIfX() {
    if (!X) {
        return;
    }

    // do 'a'
}

【讨论】:

  • 我在固件中为可以启用或禁用许多不同选项的设备执行此操作。我宁愿让我的 main() 调用 doFooIfEnabled() 之类的东西,也不愿用大量的 if 和 #ifdef 把它弄得一团糟。
  • 像任何模式一样,有时应该使用,有时不应该使用。
【解决方案2】:

这实际上取决于 x、y、z 和 a、b、c 是什么。有时 if 语句更合适。有时多态性更合适。

【讨论】:

    【解决方案3】:

    Java 中 if-else 的替代品是 switch 语句和 conditional ternary (?:) 运算符,它们都不能完全满足您的要求(仅处理 if没有else)。在我看来,您发布的代码是最好的方法。

    【讨论】:

    【解决方案4】:

    使用多态性。

    interface SomethingDoer {
        public void doSomething();
    }
    
    class ADoer implements SomethingDoer { ... }
    class BDoer implements SomethingDoer { ... }
    class CDoer implements SomethingDoer { ... }
    
    public class Main {
         public static void main (String[] args) {
              SomethingDoer doer = new SomethingDoerFactory(args).getDoer();
              doer.doSomething();
         }
    }
    

    if 并没有完全消除,而是移到了SomethingDoerFactory。此解决方案并非适用于所有情况,但在某些情况下,它是多个 if 的非常好的替代方案。

    这是一个很好的讨论:
    http://misko.hevery.com/2008/12/08/clean-code-talks-inheritance-polymorphism-testing/

    【讨论】:

    • 关于你为什么投反对票的任何意见?不是替代品吗?还是不够好被提及?
    • 如果我的条件已经基于 type,我只会考虑多态解决方案。我不会创建一个完整的类层次结构来替换 if(x) do a;
    • 如果很多情况下这是有道理的。请参阅youtube.com/watch?v=4F72VULWFvc - 谷歌技术讲座。 (The Clean Code Talks -- Inheritance, Polymorphism, & Testing)我认为投反对票是错误的。
    • 直接来自 Misko 的幻灯片:“有时 if 只是一个 if”。除非你在很多地方重复使用这些 if 语句,否则这会使事情变得不必要的复杂。另外:您的解决方案不完整。如果条件 x 和 y 都成立怎么办?你错过了AAndBDoer、AAndCDoer、BAndCDoer、AAndBAndCDoer;这些都被原始代码很好地覆盖了。
    • 显然这取决于“做一个”的确切含义。多态性可能是一个很好的解决方案,但这个例子太笼统了,无法为所有情况提供一个单一的解决方案。 AAndBDoer 等通常通过使用多态类型解决方案的装饰器/组合模式来解决。
    【解决方案5】:

    一个“真正面向对象”的答案是为“Rule”定义一个接口(使用 condition() 和 action() 方法),创建 3 个实现,将它们填充到一个集合中,然后将它们一般地迭代为在:

    List 规则 = .... ; // 你的 3 条规则在这里以某种方式初始化 for(规则 r:规则){ 如果(r.condition()){ r.action(); } }

    如果您有 300 条规则/条件,而不仅仅是 3 条,这就更有意义了。

    在 Java8 中,如果规则是 CPU 密集型的,您可能希望这样做:

    rules.parallelStream().filter(Rule::condition).forEach(Rule::action);
    

    【讨论】:

    • 您可以使用地图 O(1) 时间,而不是 O(n)。
    • 地图在这里不起作用,因为每个规则实现的条件都是唯一的。 Map 需要一个实际的键,而不是一些隐藏在可调用方法中的代码。
    【解决方案6】:

    简短的回答是肯定的。

    有时您可以避免将 if 用于条件评估和分支。 他们有适当的时刻。

    1. 多态,当行为依赖于初始值时
    2. Referrenced Assignment,当您知道可能的初始值并且它们与返回值具有 1 对 1 的相关性时。列表在这方面比数组好,但是...

      // Example:  
      if (a==1) { b=2;  }  
      if (a==2) { b=17; }  
      
      // Becomes  
      int fx(2);  // our array of answers  
      fx[0] = 2;   
      fx[1] = 17;  
      b = fx[ a - 1 ];
      
    3. 引用分支,当您知道可能的初始值并且它们与要使用的函数/分支具有 1 对 1 的相关性时。 (示例不是 Java)

      // Example:
      if (a==1) { doSomething1();  }  
      if (a==2) { doSomething2(); }  
      
      // Becomes
      function * fx(2);  // our array or better still, list of functions  
      fx[0] = &doSomething1;   
      fx[1] = &doSomething2;  
      `fx[ a - 1 ](); `
      
    4. 直接布尔赋值。

      我们讨厌:

      if (thisCondition == true) {  
        b = true;  
      } else {  
        b = false;  
      }
      

      应该是:

      b = thisCondition;

    【讨论】:

      【解决方案7】:

      您需要在某处拥有这些 if 语句。

      正如其他人所建议的那样,它们可以重构为其他方法以保持当前方法的清洁。如果您需要在多个地方重复使用相同的 set if 语句,则可能可以使用Decorator Pattern

      【讨论】:

        【解决方案8】:

        这听起来像是使用 closure 的完美案例。但为此,您需要 groovy 或类似的东西。

        【讨论】:

          【解决方案9】:

          怎么样... myAnimator(thing, pos, speed | computeSpeed());

          如果 speed === undefined 那么它将计算Speed...我想。

          【讨论】:

            【解决方案10】:

            这真的取决于上下文...但是 if-else 只是 java 中的 控制流 语句之一: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/flow.html

            【讨论】:

              【解决方案11】:

              做这样的事情,根据条件实现枚举并调用覆盖方法。

              public enum Rule{
                          a(){
                          @Override
                          public void do(){
                          // do something.
                          }
                          },
                          b(){
                          @Override
                          public void do(){
                          // do something.
                          }
                          },
                          c(){
                          @Override
                          public void do(){
                          // do something.
                          }
              
              
                          public abstract void do();
              
                          }
                      }
              
              
              
              
                   public class Test{
                          public static void main(String[] args){
                              Rule r = Rule.valueOf("a");
                              r.do();
                          }
                      }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-07-15
                • 1970-01-01
                • 1970-01-01
                • 2012-04-19
                • 2012-10-10
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多