优雅代码之消除if-else判断

臃肿示例

if-else

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;
 } else if ("modulo".equals(operator)) {
 result = a % b;
 }
 return result;
 }

case-switch

 public int calculateUsingSwitch(int a, int b, String operator) {
 int result = 0;
 switch (operator) {
 case "add":
 result = a + b;
 break;
 case "multiply":
 result = a * b;
 break;
 case "divide":
 result = a / b;
 break;
 case "subtract":
 result = a - b;
 break;
 case "modulo":
 result = a % b;
 break;
 default:
 result = Integer.MIN_VALUE;
 }
 return result;
 }

重构

工厂方式重构

  1. 抽象接口 Operation.java

 

public interface Operation {
 int apply(int a, int b);
}
  1. 加法实现 Addition.java:
public class Addition implements Operation {
 @Override
 public int apply(int a, int b) {
 return a + b;
 }
}
  1. 减法实现 Subtraction.java
public class Subtraction implements Operation {
 @Override public int apply(int a, int b) {
 return a - b;
 }
}
  1. 乘法实现 Multiplication.java
public class Multiplication implements Operation {
 @Override public int apply(int a, int b) {
 return a*b;
 }
}
  1. 除法实现 Division.java
public class Division implements Operation {
 @Override public int apply(int a, int b) {
 return a / b;
 }
}
  1. 求余实现 Modulo.java
public class Modulo implements Operation {
 @Override public int apply(int a, int b) {
 return a % b;
 }
}
  1. 工厂类 OperatorFactory.java
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class OperatorFactory {
 static Map<String, Operation> operationMap = new HashMap<>();
 static {
 operationMap.put("add", new Addition());
 operationMap.put("divide", new Division());
 operationMap.put("multiply", new Multiplication());
 operationMap.put("subtract", new Subtraction());
 operationMap.put("modulo", new Modulo());
 }
 public static Optional<Operation> getOperation(String operation) {
 return Optional.ofNullable(operationMap.get(operation));
 }
}
  1. 使用示例
public int calculateUsingFactory(int a, int b, String operator) {
 Operation targetOperation = OperatorFactory
 .getOperation(operator)
 .orElseThrow(() -> new IllegalArgumentException("Invalid Operator"));
 return targetOperation.apply(a, b);
} 

枚举方式重构

  1. 枚举实现Operator.java
public enum Operator {
 ADD {
 @Override
 public int apply(int a, int b) {
 return a + b;
 }
 },
 MULTIPLY {
 @Override
 public int apply(int a, int b) {
 return a * b;
 }
 },
 SUBTRACT {
 @Override
 public int apply(int a, int b) {
 return a - b;
 }
 },
 DIVIDE {
 @Override
 public int apply(int a, int b) {
 return a / b;
 }
 },
 MODULO {
 @Override
 public int apply(int a, int b) {
 return a % b;
 }
 };
 public abstract int apply(int a, int b);
}
  1. 封装Operator到Calculator.java
 public int calculate(int a, int b, Operator operator) {
 return operator.apply(a, b);
 }
  1. 使用示例
@Test
public void whenCalculateUsingEnumOperator_thenReturnCorrectResult() {
 Calculator calculator = new Calculator();
 int result = calculator.calculate(3, 4, Operator.valueOf("ADD"));
 assertEquals(7, result);
}

命令模式

  1. 抽象的接口
public interface Command {
 Integer execute();
}
  1. 实现类
package com.baeldung.reducingIfElse;
public class AddCommand implements Command {
 private int a;
 private int b;
 public AddCommand(int a, int b) {
 this.a = a;
 this.b = b;
 }
 @Override
 public Integer execute() {
 return a + b;
 }
}
  1. 包装
 public int calculate(Command command) {
 return command.execute();
 }
  1. 测试demo
@Test
public void whenCalculateUsingCommand_thenReturnCorrectResult() {
 Calculator calculator = new Calculator();
 int result = calculator.calculate(new AddCommand(3, 7));
 assertEquals(10, result);
}

规则引擎重构

  1. 抽象规则
public interface Rule {
 boolean evaluate(Expression expression);
 Result getResult();
}
  1. 实现规则AddRule.java
public class AddRule implements Rule {
 private int result;
 @Override
 public boolean evaluate(Expression expression) {
 boolean evalResult = false;
 if (expression.getOperator() == Operator.ADD) {
 this.result = expression.getX() + expression.getY();
 evalResult = true;
 }
 return evalResult;
 }
 @Override
 public Result getResult() {
 return new Result(result);
 }
}

其中:返回结果

public class Result {
 int value;
 public Result(int value) {
 this.value = value;
 }
 public int getValue() {
 return value;
 }
}

表达式

public class Expression {
 private Integer x;
 private Integer y;
 private Operator operator;
 public Expression(Integer x, Integer y, Operator operator) {
 this.x = x;
 this.y = y;
 this.operator = operator;
 }
 public Integer getX() {
 return x;
 }
 public Integer getY() {
 return y;
 }
 public Operator getOperator() {
 return operator;
 }
}

规则引擎RuleEngine.java

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
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();
 }
}
  1. 测试demo
@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或者case-switch进行改造,使用工厂方法,枚举方法,命令模式,规则引擎方式不同方法进行尝试,最后使用设计模式的六大原则对代码进行评估。

posted @ 2019-08-06 14:50  农名工进城  阅读(1190)  评论(0编辑  收藏  举报