当前位置:   article > 正文

探讨if...else的替代方案_if-elif-else 可以完全替换if嵌套吗

if-elif-else 可以完全替换if嵌套吗

大家在开发过程中,经常会用到if..else..语句,对于分支较少的业务场景来说还好,如果业务分支较多,那if..else..语句就显得非常臃肿,就会大大的影响代码可读性和可维护性。

039110f89140d9c69f220e7dfeee09e8.png

针对这个问题,笔者就介绍几种if..else的替代方案。

业务需求

 

假设我们要做一个计算器,实现加减乘除的需求。使用if...else...语句实现代码如下:

  1. public static int calculate(int a, int b, String operator) {
  2. int result = Integer.MIN_VALUE;
  3. if ("add".equals(operator)) {
  4. result = a + b;
  5. } else if ("multiply".equals(operator)) {
  6. result = a * b;
  7. } else if ("divide".equals(operator)) {
  8. result = a / b;
  9. } else if ("subtract".equals(operator)) {
  10. result = a - b;
  11. }
  12. return result;
  13. }

 

当然也可以使用swith语句实现。

 

  1. public static int calculateUsingSwitch(int a, int b, String operator) {
  2. int result = 0;
  3. switch (operator) {
  4. case "add":
  5. result = a + b;
  6. break;
  7. case "subtract":
  8. result = a - b;
  9. case "divide":
  10. result = a / b;
  11. break;
  12. case "multiply":
  13. result = a * b;
  14. }
  15. return result;
  16. }

 

但是随着运算条件越来越多,则实现逻辑的复杂度则会越来越高,同时越来越难维护。

重构方案

 

1.工厂模式

创建一个工厂方法,返回一个给定类型的对象,并根据具体对象的操作行为来执行操作。

1.将操作抽象成一个Operation接口。

 

  1. public interface Operation {
  2. int apply(int a, int b);
  3. }

 

2.分别实现加减乘除四个方法。

  1. public class Addition implements Operation {
  2. @Override
  3. public int apply(int a, int b) {
  4. return a + b;
  5. }
  6. }
  7. public class Division implements Operation{
  8. @Override
  9. public int apply(int a, int b) {
  10. return a - b;
  11. }
  12. }
  13. // other case

 

然后通过操作工厂提供加减乘除操作。

 

  1. import java.util.HashMap;
  2. import java.util.Map;
  3. import java.util.Optional;
  4. public class OperatorFactory {
  5. static Map<String, Operation> operationMap = new HashMap<>();
  6. static {
  7. operationMap.put("add", new Addition());
  8. operationMap.put("divide", new Division());
  9. // more operators
  10. }
  11. public static Optional<Operation> getOperation(String operator) {
  12. return Optional.ofNullable(operationMap.get(operator));
  13. }
  14. }

 

3.调用

 

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

 

新增运算操作只需要维护操作工厂的operationMap即可。

 

2.使用枚举

除了使用Map之外,还可以使用Enum来标记业务逻辑。

 

  1. 我们需要定义加减乘除的Enum。

 

  1. public enum Operator {
  2. ADD, MULTIPLY, SUBTRACT, DIVIDE
  3. }

 

枚举表示不同运算符操作,为每个Enum值定义运算操作。例如

 

  1. ADD {
  2. @Override
  3. public int apply(int a, int b) {
  4. return a + b;
  5. }
  6. },
  7. // other operators
  8. public abstract int apply(int a, int b);

 

  1. 在计算器类中,可以定义一个方法来执行该操作。

  1. public int calculate(int a, int b, Operator operator) {
  2. return operator.apply(a, b);
  3. }

 3. 可以通过使用Operator#valueOf()方法将字符串值转换为操作符来调用该方法。

 

  1. @Test
  2. public void whenCalculateUsingEnumOperator_thenReturnCorrectResult() {
  3. Calculator calculator = new Calculator();
  4. int result = calculator.calculate(3, 4, Operator.valueOf("ADD"));
  5. assertEquals(7, result);
  6. }

3.命令模式

在前面的讨论中,使用工厂类为给定的操作返回业务对象的实例。还可以设计一个Calculator#calculate方法来接受一个可以在输入端执行的命令。这是替代嵌套if语句的另一种方式—命令模式

  1. 定义命令接口

     

    1. public interface Command {
    2. Integer execute();
    3. }
  2. 来实现一个加法运算类AddCommand。

     

    1. public class AddCommand implements Command {
    2. // Instance variables
    3. public AddCommand(int a, int b) {
    4. this.a = a;
    5. this.b = b;
    6. }
    7. @Override
    8. public Integer execute() {
    9. return a + b;
    10. }
    11. }
  3. 在计算器中引入一个新方法,接受并执行命令。

    1. public int calculate(Command command) {
    2. return command.execute();
    3. }
  4. 实例一个AddCommand,并将其传递给Calculator#calculate方法。

 

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

 

4.规则引擎

 

当我们写下大量嵌套的if语句时,每个条件都描述了一条业务规则,以获得正确的逻辑处理。可以使用一个规则引擎降低将这种代码的复杂性。规则引擎对规则进行评估,并根据输入返回结果。来通过一个例子,设计一个简单的RuleEngine,通过一组规则来处理一个表达式,并返回所选规则的结果。

  1. 定义一个规则接口。

 

  1. public interface Rule {
  2. boolean evaluate(Expression expression);
  3. Result getResult();
  4. }

 2. 实现一个RuleEngine。

 

  1. public class RuleEngine {
  2. private static List<Rule> rules = new ArrayList<>();
  3. static {
  4. rules.add(new AddRule());
  5. }
  6. public Result process(Expression expression) {
  7. Rule rule = rules
  8. .stream()
  9. .filter(r -> r.evaluate(expression))
  10. .findFirst()
  11. .orElseThrow(() -> new IllegalArgumentException("Expression does not matches any Rule"));
  12. return rule.getResult();
  13. }
  14. }

 

规则引擎接受一个表达式对象并返回结果,把表达式类设计成由两个整数对象和将被应用的运算符组成的一组。

 

  1. public class Expression {
  2. private Integer x;
  3. private Integer y;
  4. private Operator operator;
  5. }

 

  1. 定义一个自定义的AddRule类,它只在指定ADD操作时进行评估。

     

    1. public class AddRule implements Rule {
    2. @Override
    3. public boolean evaluate(Expression expression) {
    4. boolean evalResult = false;
    5. if (expression.getOperator() == Operator.ADD) {
    6. this.result = expression.getX() + expression.getY();
    7. evalResult = true;
    8. }
    9. return evalResult;
    10. }
    11. }
  2. 用一个表达式来调用RuleEngine。

@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的替代方法不止这些,这里抛砖引玉,大家可以发散脑洞,可以尝试更多类似的解法。

 

 

 

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/377907
推荐阅读
相关标签
  

闽ICP备14008679号