If-Else 是最简单的处理分支逻辑的方案,但是它会导致代码重构困难、可读性变差等等

if (condition) {
    // do something
} else if (otherCondition) {
    // do something else
} else {
    // default
}

分享一些技巧和思路来将If-Else转换成其他可读性高的代码


情况1——没有必要的If-Else

public void operation(int input){
    if (input > 5) {
        // do something
    } else {
        // do something else
    }
}

上面这就是最简答的形式,但是这完全可以删除掉else

public void operation(int input){
    if (input > 5) {
        //do something
        return;
    }
    // do something else
}

情况2——分情况给变量赋值时

public static String determineGender(int input) {
    String gender;

    if (input == 0) {
        gender = "male";
    } else if (input == 1) {
        gender = "female";
    } else {
        gender = "unknown";
    }

    return gender;
}

虽然看上去没什么问题,但是实际上大佬们都会觉得很糟糕。因为这里不仅可以使用switch来代替if-else,而且还可以删去else来让代码看上去更加干净整洁

public static String determineGender(int input) {
        if (input == 0) return "male";
        if (input == 1) return "female";
        return "unknown";
}

检查前提条件

如果方法被传入了一个无效的值,那么继续执行方法就是毫无意义的。在上面的例子中,如果要保证传入的值为0或者1,我们需要提供一种验证的手段。

普通方式:先执行一个方法来验证输入值是否为0或者1

// A method checking whether input is 0 or 1.
public String determineGender(int input){
    // Continue executing logic
}

更加清爽的方式:应用防御性编码技术来重写:

public static String determineGender(int input) {
        if (input < 0) throw new IllegalArgumentException();
        if (input > 0) throw new IllegalArgumentException();
        return input == 0 ? "male" : "female";
    }

现在,我们可以确保仅在值落在预期范围内时才执行主逻辑。IF 也已可以被三元运算符代替,因为不再需要在结尾处默认返回unknown。


将If-Else转换为字典,完全避免If-Else

如果我们需要执行一些操作,这些操作会根据某些条件进行选择,我们知道未来肯定还要添加更多操作

public void performOperation(String operationName) {
    if (operationName == "op1") {
        // do something
    } else if (operationName == "op2") {
        // do something else
    } else {
        // default
    }
}

可以使用久经考验的If-Else,如果添加操作则只需要简单的添加其他内容即可,十分简单。但是就维护而言,这并不是一种好的设计。

知道以后需要添加的新操作后,可以将If-Else重构成为键值对

public void performOperation(String operationName) {
    var operations = new HashMap<String, ActionMethod>();
    //operation键值对可以在其他地方被事先定义好
    operations["op1"] = () -> {/* do something */};
    operations["op2"] = () -> {/* do something else */};

    operations[operationName].invoke();
}

此时可读性已经大大提高,而且可以更加轻松的推断出该代码。

Last modification:May 11th, 2021 at 09:45 pm