如何在多个if-else中处理标志


10

我似乎经常在我的代码和其他代码中看到这一点。似乎没有什么比这更糟糕的了,但是它看起来可以做得更好,这让我很烦。我猜想一个case语句可能更有意义,但是变量通常不是一个很好的类型,或者根本不能与case语句一起使用(取决于语言)

If variable == A
    if (Flag == true)
        doFooA()
    else
        doFooA2

else if variable == B
    if (Flag == true)
        doFooB()
    else
        doFooB2
else if variable == C
    if (Flag == true)
        doFooC()
    else
        doFooC2

似乎有多种方法可以“分解”,例如2套if-elses,其中一组在Flag == true时处理。

是否有“好方法”将其分解,或者如果这种if-else算法发生,通常意味着您做错了什么?


6
是否可以将Flag变量传递给可以处理标志本身的doFooX?
让-弗朗索瓦的Côté

当然可以,但是您只有一个方法doFooX,该方法将评估标志是否为true,然后执行doFooX1或doFooX2
TruthOf42 2013年

5
恕我直言,它仍然会更清晰地阅读。然后,它依靠什么doFooA和doFooA2做...
让-弗朗索瓦的Côté

2
为什么写if (Flag == true)而不是仅仅写If (Flag)?如果您认为If (Flag == true)更好,为什么不if ((Flag == true) == true)呢?
Keith Thompson

1
从以下大多数答案中得出的最重要的结论是,就逻辑流程和代码的未来维护而言,简单性和易读性比巧妙的技巧更为重要
Patrick Hughes 2013年

Answers:


18

可以使用多态来处理。

factory(var, flag).doFoo();

每当您对某物的类型进行一堆if / else检查时,您可以考虑将if / else检查集中在工厂方法中,然后多态调用doFoo()。但这对于一劳永逸的解决方案来说可能会过分杀人。

也许您可以创建一个键/值映射,其中键是var / flag,而值是函数本身。

do[var, flag]();

2
+1:表查询几乎每次都击败嵌套的if语句。
凯文·克莱恩

1
我想说这是最好的解决方案。
松饼人

6

多个嵌套的if增加了代码的循环复杂性。直到最近,一个函数中有多个退出点都被认为是糟糕的结构化代码,但是现在,只要代码简单,简短,就可以这样做,使代码的读取变得很简单:

    if (variable == A && Flag) {
        doFooA();
        return;
    }

    if (variable == A) {
        doFooA2();
        return;
    }

    if (variable == B && Flag){
        doFooB();
        return;
    }

    if (variable == B){
        doFooB2();
        return;
    }

    if (variable == C && Flag){
         doFooC();
         return;
    }

    if (variable == C){
         doFooC2();
    }

    return;

3

另一个选择是组合if和switch。这并不优于您的嵌套if技术,但可以减少重复测试的次数(如果开关针对跳转表进行了优化)。


if (flag)
{
    switch (variable)
    {
        case A:
           ... blah
           break;

        case B:
           ... blah
           break;

        case C:
           ... blah
           break;

        default:
           ... log an error.
           ... maybe do a default action.
           break;
    }
}
else // flag == false
{
    switch (variable)
    {
        case A:
           ... blah
           break;

        case B:
           ... blah
           break;

        case C:
           ... blah
           break;

        default:
           ... log an error.
           ... maybe do a default action.
           break;
}

0

好吧,总有这个...

if variable == A && Flag
    doFooA()
else if variable == A 
    doFooA2    
else if variable == B && Flag
    doFooB()
else if variable == B
    doFooB2
else if variable == C && Flag
     doFooC()
else if variable == C
     doFooC2

但坦率地说,我认为最初的代码还不错。


0

使用多态和rule数组

interface IRule() {
  boolean applicable(args...);
  obj apply(args...);
}

static final Array<IRule> rules = [new MeaningfulNameRule1(), new MeaningfulNameRule2(), ...];

/* where */
class MeaningfulNameRuleX extends IRule{ /* */ }

/* In your method */

for (rule in rules) {
  if (rule.applicable(a,b,c)){
    return rule.apply(e,f,g);
  }
}

或如mike30建议的那样:如果规则条件可以轻松构成键,那么哈希表是最好的选择。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.