java:多if语句的重构

jckbn6z7  于 2021-07-09  发布在  Java
关注(0)|答案(4)|浏览(426)

“多if语句”是一种标准的代码味道。有很多方法可以重构它。在简单的情况下,我尝试使用策略模式。但最近我运行了一个代码,其中使用了多个具有int范围的if语句。我也不知道怎么把代码弄干净。
下面是这样一个代码的示例:

public void calculate(int i) {
    if(i > 0 && i < 5) {
        // do smth
    } else if(i > 4 && i < 10) {
        //do smth
    } else if (i >= 10 && i <20 ) {
        //do smth
    }
    //...
    else if (i > 90 && i < 100) {
        //do smth
    }
}

为了使用策略,我尝试将每个范围提取到某个逻辑单元,但所有这些if语句都只是从这个方法中移出,根本不会消失。
有没有办法重构这样的if语句(即检查int范围的地方)?

p4rjhz4m

p4rjhz4m1#

可考虑的设计模式:
面对一个类似的问题(对icao squawk值进行稀疏的范围测试),我也被代码中相当混乱的外观弄糊涂了。
我的解决方案是一个执行范围测试的静态函数,然后简单地调用它来计算'between'测试(如果有一个java between函数,我不知道它……)。下面是我如何解决这个问题的片段;不是一个好的模式,但也许这引发了另一个解决方案的想法。

/**
 * Range test shorthand 
 * 
 * @param value - value to test
 * @param min   - lower bound
 * @param max   - upper bound
 * 
 * @return  true | false  
 */
private static boolean inRange(int value, int min, int max){
    return min <= value && value <= max;
}

我就是这么用的:

// not a pre-defined code...  run some range tests next to quess
    if (inRange(squawk,41,57)) {
        message = "test";
    }
    else if (inRange(squawk,100,400)){
        message = "Unique Purpose and Experimental activities";  // ud 17-OCT
    }
    else if (inRange(squawk,100,700)){  // Note! this is an overlap defined IN Order 7110.66E
        message = "Oceanic Airspace";   // ud 17-OCT
    }
    else if (inRange(squawk,1207,1272)){
        message = "DVFR Aircraft (USA)";  // ud 17-OCT
    }
    else if (inRange(squawk,1273,1275)){
        message = "Calibration Performance Monitoring Equipment";
    }

[...]
使用简单的级联将不适合我,因为它是一个稀疏集,而且还涉及到一个Map(以下是其中的一部分,供参考):

private static final Map<Integer,String> codes;
static {
    codes = new HashMap<Integer,String>();

    /* unremarkable codes */
    codes.put(0,    "");
    codes.put(0000, "");  // there message defined for 0000 in 7110.66E spec, but I'm using an empty string
    codes.put(0021, "VFR below 5000ft.");
    codes.put(0022, "VFR above 5000ft.");
    codes.put(0033, "Parachute Drop Operations");
    codes.put(0100, "Airport Flight Operations");
    codes.put(0500, "External ARTCC subsets");
    codes.put(0600, "External ARTCC subsets");
    codes.put(0700, "External ARTCC subsets");
u0njafvf

u0njafvf2#

这不是说明这一点的最好例子。
这段代码相对干净是有争议的。这当然很容易理解,也许比复杂的战略模式更容易理解。当多态性发挥作用时,我想到了策略。
使用 Map ,其中键是范围中的最大值,值是来自 java.util.function 在jdk8中打包。也许inttodoublefunction是您所需要的。
为什么你的计算方法看起来毫无作用?它不应该返回一个计算结果吗?

private Map<Integer, IntToDoubleFunction> strategy = new TreeMap<Integer, IntToDoubleFunction>() {{
    put(5, new IntToDoubleFunction() { // add function here });
    put(90, new IntToDoubleFunction() { // add function here });
}};

void calculate(int input) {
    double result = 0.0;
    for (Integer maxValueInRange: this.strategy.keySet()) {
        if (input <= maxValueInRange) {
            result = this.strategy.get(maxValueInRange).applyAsDouble(input);
            break;
            // what happens to result?
        }
    }
}
np8igboo

np8igboo3#

试着改变

if(i > 0 && i < 5) {
    // do smth
} else if(i > 4 && i < 10) {
    //do smth
} else if (i >= 10 && i <20 ) {
    //do smth
}
//...
else if (i > 90 && i < 100) {
    //do smth
}

例如:

if(i > 0){
  if ( i < 5 ){

  } else if (i < 10 ) {
  //
  }
}

更简单,结果也一样

wtlkbnrh

wtlkbnrh4#

我不认为没有if分支是一个很好的方法,但是你可以跳过下限,因为你正在使用 else if 例如

public void calculate(int i) {
    if( i <= 0) {
        return;
    } else if(i < 5) {
        // do smth
    } else if(i < 10) {
        //do smth
    } else if (i <20 ) {
        //do smth
    }
    //...
    else if (i < 100) {
        //do smth
    }
}

编辑:将其更新为包含0大小写。谢谢斯图尔图斯克

相关问题