1. 概述

条件判断语句是编程语言中不可或缺的一部分,但在实际开发中,我们经常会写出大量嵌套的 if 语句,导致代码变得臃肿、难以维护。

本文将带你了解 替代多重嵌套 if 语句的多种方式,让你的代码更简洁、更易维护。

我们将会结合一个典型的业务场景,逐步展示如何通过设计模式和重构技巧优化代码结构。

2. 场景示例

我们以一个简单的计算器类为例,它接收两个整数和一个操作符(如 "add""multiply" 等),然后根据操作符返回计算结果。

最原始的做法是使用多个 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;
    }
    return result;
}

也可以用 switch 来实现:

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

优点:直观易懂
缺点

  • 当条件变多时,维护成本高
  • 扩展性差,新增操作需要修改原有方法
  • 复杂条件难以表达

⚠️ 注意switch 虽然比 if-else 更清晰,但依然不适合处理复杂逻辑。

3. 重构方案

接下来,我们将介绍几种常见的重构策略,帮助你把复杂的 if 判断替换为更加优雅的设计。

3.1. 工厂类 + 多态

在很多场景下,每个分支只是执行不同的行为。我们可以借助工厂模式 + 多态,将具体逻辑封装到独立类中。

✅ 步骤如下:

  1. 定义统一接口 Operation
public interface Operation {
    int apply(int a, int b);
}
  1. 实现具体的加法类:
public class Addition implements Operation {
    @Override
    public int apply(int a, int b) {
        return a + b;
    }
}
  1. 创建工厂类管理所有操作:
public class OperatorFactory {
    static Map<String, Operation> operationMap = new HashMap<>();
    static {
        operationMap.put("add", new Addition());
        operationMap.put("divide", new Division());
        // 可继续扩展
    }

    public static Optional<Operation> getOperation(String operator) {
        return Optional.ofNullable(operationMap.get(operator));
    }
}
  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);
}

优势

  • 高内聚低耦合
  • 易于扩展新操作
  • 主逻辑清晰无分支

⚠️ 注意:避免把 if 移植到工厂类中,那样就换汤不换药了。

3.2. 枚举策略

除了使用 Map 和工厂,我们还可以利用 Java 枚举的强大特性来简化逻辑。

✅ 步骤如下:

  1. 定义操作枚举:
public enum Operator {
    ADD, MULTIPLY, SUBTRACT, DIVIDE
}
  1. 在枚举中直接定义行为:
ADD {
    @Override
    public int apply(int a, int b) {
        return a + b;
    }
},
// 其他操作...

public abstract int apply(int a, int b);
  1. Calculator 中调用:
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);
}

优势

  • 类型安全
  • 枚举天然支持 switch-case
  • 逻辑集中,避免分支爆炸

3.3. 命令模式

命令模式是另一种优雅的方式,尤其适合需要灵活组合操作的场景。

✅ 步骤如下:

  1. 定义命令接口:
public interface Command {
    Integer execute();
}
  1. 实现具体命令:
public class AddCommand implements Command {
    private int a, b;

    public AddCommand(int a, int b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public Integer execute() {
        return a + b;
    }
}
  1. Calculator 中接受命令对象:
public int calculate(Command command) {
    return command.execute();
}
  1. 调用示例:
@Test
public void whenCalculateUsingCommand_thenReturnCorrectResult() {
    Calculator calculator = new Calculator();
    int result = calculator.calculate(new AddCommand(3, 7));
    assertEquals(10, result);
}

优势

  • 支持延迟执行、撤销等高级功能
  • 解耦请求发送者与接收者
  • 便于组合多个操作

3.4. 规则引擎

当业务规则复杂且动态变化时,可以考虑引入轻量级规则引擎。

✅ 示例结构如下:

  1. 定义规则接口:
public interface Rule {
    boolean evaluate(Expression expression);
    Result getResult();
}
  1. 实现规则引擎:
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. 表达式类:
public class Expression {
    private Integer x;
    private Integer y;
    private Operator operator;        
}
  1. 具体规则类:
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;
    }    
}
  1. 测试调用:
@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());
}

优势

  • 规则可配置化
  • 易于维护复杂的业务逻辑
  • 支持热加载、动态更新

4. 总结

本文介绍了以下几种常见的替代多重 if 的方式:

方式 适用场景 优势
工厂 + 多态 固定操作集 易扩展,职责分离
枚举策略 简单逻辑 类型安全,代码简洁
命令模式 动态操作 支持组合、延迟执行
规则引擎 复杂业务逻辑 可配置,易维护

选择哪种方式取决于你的具体需求,但在实际开发中,尽量避免写出层层嵌套的 if 语句,这不仅影响可读性,也增加了维护难度。

📌 小贴士:合理运用设计模式不仅能提升代码质量,也能让你在团队协作中脱颖而出。

完整代码可参考 GitHub 仓库


原始标题:How to Replace Many if Statements in Java | Baeldung