“多个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范围的地方)?
答案 0 :(得分:4)
这不是表达这一点的最好例子。
这个代码相对干净是有争议的。它当然很容易阅读,也许比复杂的战略模式更容易阅读。当多态性发挥作用时,我会想到策略。
使用Map
可以轻松清除此示例,其中键是范围中的最大值,值是JDK 8中java.util.function
包的接口类型引用。或许{ {3}}就是你所需要的。
为什么您的计算方法似乎什么都不做?它不应该返回计算结果吗?
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?
}
}
}
答案 1 :(得分:2)
我不认为没有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个案例。谢谢Stultuske
答案 2 :(得分:1)
尝试改变
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 ) {
//
}
}
更简单,并导致相同的结果
答案 3 :(得分:0)
要考虑的可能设计模式:
面对类似的问题(范围测试ICAO Squawk值与稀疏性),我也被代码的相当混乱的外观所困扰。
我的解决方案是一个执行范围测试的静态函数,然后简单地调用它来计算&#39;之间的关系。测试(如果函数之间有Java,我不知道它......)。以下是我如何解决这个问题的片段;对于一切都不是一个好的模式,但也许这激发了另一个解决方案的想法。
/**
* 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";
}
[...]
使用简单的级联对我来说不起作用,因为它是稀疏集合,并且还涉及到地图......(这里是其中的一部分,供参考):
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");