Java中大量if...else語(yǔ)句的消除替代方案

在我們平時(shí)的開(kāi)發(fā)過(guò)程中,經(jīng)??赡軙?huì)出現(xiàn)大量If else的場(chǎng)景,代碼顯的很臃腫,非常不優(yōu)雅。那我們又沒(méi)有辦法處理呢?

針對(duì)大量的if嵌套讓代碼的復(fù)雜性增高而且難以維護(hù)。本文將介紹多種解決方案。

案例

下面模擬業(yè)務(wù)邏輯,根據(jù)傳入的條件作出不同的處理方式。

拿一個(gè)計(jì)算器類當(dāng)做案例,有加減乘除四種方法,輸出結(jié)果和四種操作有關(guān)。

public int calculate(int a, int b, String operator) {
    int result = Integer.MIN_VALUE;
    if ("add".equals(operator)) {
        result = a + b;
    } else if ("multiply".equals(operator)) {
        result = a * b;
    } else if ("divide".equals(operator)) {
        result = a / b;
    } else if ("subtract".equals(operator)) {
        result = a - b;
    }
    return result;
}

當(dāng)然也可以用switch來(lái)實(shí)現(xiàn)。

public int calculateUsingSwitch(int a, int b, String operator) {
    switch (operator) {
      case "add":
        result = a + b;
        break;
        // other cases
    }
    return result;
}

隨著條件越來(lái)越多,復(fù)雜性也增高,也越來(lái)越難以維護(hù)。

重構(gòu)

1、工廠類我們將操作進(jìn)行抽象給出一個(gè)操作接口

public interface Operation {
    int apply(int a, int b);
}

然后實(shí)現(xiàn)加減乘除四個(gè)方法

public class Addition implements Operation {
    
    @Override
    public int apply(int a, int b) {
        return a + b;
    }
}

然后通過(guò)操作工廠提供操作

public class OperatorFactory {
    static Map<String, Operation> operationMap = new HashMap<>();
    static {
        operationMap.put("add", new Addition());
        operationMap.put("divide", new Division());
        // more operators
    }
    
    public static Optional<Operation> getOperation(String operator) {
        return Optional.ofNullable(operationMap.get(operator));
    }
}

調(diào)用

public int calculateUsingFactory(int a, int b, String operator) {
    Operation targetOperation = OperatorFactory
      .getOperation(operator)
      .orElseThrow(() -> new IllegalArgumentException("Invalid Operator"));
    return targetOperation.apply(a, b);
}

新增操作只需要維護(hù)操作工廠的operationMap即可。

2、使用枚舉

在枚舉中定義操作,如下:

public enum Operator {
    ADD, MULTIPLY, SUBTRACT, DIVIDE
}

然而不同的操作對(duì)應(yīng)的邏輯不一樣,我們編寫抽象方法

ADD {
    @Override
    public int apply(int a, int b) {
        return a + b;
    }
},
// other operators
public abstract int apply(int a, int b);

調(diào)用時(shí)直接傳入枚舉值

public int calculate(int a, int b, Operator operator) {
    return operator.apply(a, b);
}
@Test
public void whenCalculateUsingEnumOperator_thenReturnCorrectResult() {
    Calculator calculator = new Calculator();
    int result = calculator.calculate(3, 4, Operator.valueOf("ADD"));
    assertEquals(7, result);
}

3、命令模式

定義命令接口。

public interface Command {
    Integer execute();
}

實(shí)現(xiàn)加法

public class AddCommand implements Command {
    // Instance variables
    public AddCommand(int a, int b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public Integer execute() {
        return a + b;
    }
}

定義一個(gè)Calculator類,加入執(zhí)行命令的方法。

public int calculate(Command command) {
    return command.execute();
}

測(cè)試代碼

@Test
public void whenCalculateUsingCommand_thenReturnCorrectResult() {
    Calculator calculator = new Calculator();
    int result = calculator.calculate(new AddCommand(3, 7));
    assertEquals(10, result);
}

4、規(guī)則引擎

定義規(guī)則接口

public interface Rule {
    boolean evaluate(Expression expression);
    Result getResult();
}

實(shí)現(xiàn)規(guī)則引擎

public class RuleEngine {

    private static List<Rule> rules = new ArrayList<>();
    static {
        rules.add(new AddRule());
    }
    
    public Result process(Expression expression) {
        Rule rule = rules.stream()
          .filter(r -> r.evaluate(expression))
          .findFirst()
          .orElseThrow(() -> new IllegalArgumentException("Expression does not matches any Rule"));
        return rule.getResult();
    }
}

定義表達(dá)式

public class Expression {
    private Integer x;
    private Integer y;
    private Operator operator;
}

定義加法規(guī)則

public class AddRule implements Rule {

    @Override
    public boolean evaluate(Expression expression) {
        boolean evalResult = false;
        if (expression.getOperator() == Operator.ADD) {
            this.result = expression.getX() + expression.getY();
            evalResult = true;
        }
      return evalResult;
    }
}

給規(guī)則引擎?zhèn)魅氡磉_(dá)式來(lái)調(diào)用

@Test
public void whenNumbersGivenToRuleEngine_thenReturnCorrectResult() {
    Expression expression = new Expression(5, 5, Operator.ADD);
    RuleEngine engine = new RuleEngine();
    Result result = engine.process(expression);

    assertNotNull(result);
    assertEquals(10, result.getValue());
}

總結(jié)雖然說(shuō)常見(jiàn)的代碼中if...else不可避免,但濫用 if...else 會(huì)對(duì)代碼的可讀性、可維護(hù)性造成很大傷害。因此,使用好 if...else,讓代碼清爽對(duì)于你的項(xiàng)目長(zhǎng)遠(yuǎn)考慮有十分重要的意義。

英文原文:https://www.baeldung.com/java-replace-if-statements

其他參考資料:

策略設(shè)計(jì)模式:http://www.runoob.com/design-pattern/strategy-pattern.html

命令設(shè)計(jì)模式:http://www.runoob.com/design-pattern/command-pattern.html

推薦閱讀:

Java8中遍歷Map的常用四種方式

推薦一些MySQL優(yōu)化技巧,效率提升不止十倍!

44個(gè)Java代碼優(yōu)化手段,保證性能溜溜的!

掃碼關(guān)注公眾號(hào),發(fā)送關(guān)鍵詞獲取相關(guān)資料:
  1. 發(fā)“Springboot”領(lǐng)取電商項(xiàng)目實(shí)戰(zhàn)源碼;

  2. 發(fā)“SpringCloud”領(lǐng)取學(xué)習(xí)實(shí)戰(zhàn)資料;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容