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

在我們平時的開發過程中,經常可能會出現大量If else的場景,代碼顯的很臃腫,非常不優雅。那我們又沒有辦法處理呢?

針對大量的if嵌套讓代碼的複雜性增高而且難以維護。本文將介紹多種解決方案。

案例

下面模擬業務邏輯,根據傳入的條件作出不同的處理方式。

拿一個計算器類當做案例,有加減乘除四種方法,輸出結果和四種操作有關。

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;
}

當然也可以用switch來實現。

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

隨着條件越來越多,複雜性也增高,也越來越難以維護。

重構

1、工廠類我們將操作進行抽象給出一個操作接口

 

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

然後實現加減乘除四個方法

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

然後通過操作工廠提供操作

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));
    }
}

調用

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

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

2、使用枚舉

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

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

然而不同的操作對應的邏輯不一樣,我們編寫抽象方法

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

調用時直接傳入枚舉值

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();
}

實現加法

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;
    }
}

定義一個Calculator類,加入執行命令的方法。

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

測試代碼

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

4、規則引擎

定義規則接口

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

實現規則引擎

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();
    }
}

定義表達式

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

定義加法規則

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;
    }
}

給規則引擎傳入表達式來調用

@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());
}

總結雖然說常見的代碼中if...else不可避免,但濫用 if...else 會對代碼的可讀性、可維護性造成很大傷害。因此,使用好 if...else,讓代碼清爽對於你的項目長遠考慮有十分重要的意義。

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

其他參考資料:

策略設計模式:http://www.runoob.com/design-pattern/strategy-pattern.html

命令設計模式:http://www.runoob.com/design-pattern/command-pattern.html

推薦閱讀:

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

推薦一些MySQL優化技巧,效率提升不止十倍!

44個Java代碼優化手段,保證性能溜溜的!

掃碼關注公衆號,發送關鍵詞獲取相關資料:

  1. 發“Springboot”領取電商項目實戰源碼;

  2. 發“SpringCloud”領取學習實戰資料;

發佈了27 篇原創文章 · 獲贊 73 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章