用 set或map修复if-else的坏味道 - egkatzioura


有时,我们的代码库中可能会出现一些巨大的“if”语句。必须维护这些语句并一遍又一遍地更改相同的代码块。这在“if”语句检查变量是否属于某个值范围的情况下也很常见。
假设你有一个枚举:

public enum FoodType {
 
    FRUIT,
    VEGETABLES,
    RED_MEAT,
    WHITE_MEAT,
    FISH,
    DIARY,
    CERIAL
}

public String recommend(FoodType foodType) {
 
    if(foodType==FoodType.FISH||foodType==FoodType.RED_MEAT||foodType==FoodType.WHITE_MEAT) {
 
        //execute a procedure
    } else if(foodType==FoodType.FRUIT||foodType==FoodType.VEGETABLES) {
       
//execute a procedure
    } else {
       
//execute a procedure
    }
}

上面代码中:鱼、红肉和白肉适合喜欢蛋白质饮食的用户,而水果和蔬菜更适合以纤维为基础的饮食。在未来的情况下,这个枚举可能会得到增强,并添加更多的食物类型。'if' 代码块将不得不更改。此外,如果在其他文件中使用了这个复杂的“if”语句,您将不得不更改每个文件。您不仅会有一个巨大的 if 块,而且还有一个必须在每个文件上维护的块,这可能容易出错。
为了避免这种情况,您可以将 if 语句的内容更改为函数。

package com.gkatzioura;
 
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
 
import static com.gkatzioura.FoodType.*;
 
public class DietFilter {
 
    private static final Set FOODS_WITH_PROTEIN = Collections.unmodifiableSet(new HashSet(Arrays.asList(
            FISH,
            RED_MEAT,
            WHITE_MEAT)));
 
    private static final Set FOODS_WITH_FIBER = Collections.unmodifiableSet(new HashSet(Arrays.asList(
            FRUIT,
            VEGETABLES)));
 
    public static boolean proteinBased(FoodType foodType) {
        return FOODS_WITH_PROTEIN.contains(foodType);
    }
 
    public static boolean fiberBased(FoodType foodType) {
        return FOODS_WITH_FIBER.contains(foodType);
    }
 
}

因此,我们没有添加食物类型的每个单个案例,而是在“if”语句中创建了一个函数,该函数检查给定的参数是否属于特定组。
因此,您的“if”语句将更改为此。

public String recommend(FoodType foodType) {
 
    if(DietFilter.proteinBased(foodType)) {
 
        //execute a procedure
    } else if(DietFilter.fiberBased(foodType)) {
       
//execute a procedure
    } else {
       
//execute a procedure
    }
}

如果将更多食物类型添加到枚举中,开发人员只需更改集合的构造并添加额外的食物类型。这比更改代码的多个部分要容易得多,而且更具可读性。