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. 工厂类 + 多态
在很多场景下,每个分支只是执行不同的行为。我们可以借助工厂模式 + 多态,将具体逻辑封装到独立类中。
✅ 步骤如下:
- 定义统一接口
Operation
:
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());
// 可继续扩展
}
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);
}
✅ 优势:
- 高内聚低耦合
- 易于扩展新操作
- 主逻辑清晰无分支
⚠️ 注意:避免把 if
移植到工厂类中,那样就换汤不换药了。
3.2. 枚举策略
除了使用 Map 和工厂,我们还可以利用 Java 枚举的强大特性来简化逻辑。
✅ 步骤如下:
- 定义操作枚举:
public enum Operator {
ADD, MULTIPLY, SUBTRACT, DIVIDE
}
- 在枚举中直接定义行为:
ADD {
@Override
public int apply(int a, int b) {
return a + b;
}
},
// 其他操作...
public abstract int apply(int a, int b);
- 在
Calculator
中调用:
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);
}
✅ 优势:
- 类型安全
- 枚举天然支持 switch-case
- 逻辑集中,避免分支爆炸
3.3. 命令模式
命令模式是另一种优雅的方式,尤其适合需要灵活组合操作的场景。
✅ 步骤如下:
- 定义命令接口:
public interface Command {
Integer execute();
}
- 实现具体命令:
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;
}
}
- 在
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);
}
✅ 优势:
- 支持延迟执行、撤销等高级功能
- 解耦请求发送者与接收者
- 便于组合多个操作
3.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());
}
✅ 优势:
- 规则可配置化
- 易于维护复杂的业务逻辑
- 支持热加载、动态更新
4. 总结
本文介绍了以下几种常见的替代多重 if
的方式:
方式 | 适用场景 | 优势 |
---|---|---|
工厂 + 多态 | 固定操作集 | 易扩展,职责分离 |
枚举策略 | 简单逻辑 | 类型安全,代码简洁 |
命令模式 | 动态操作 | 支持组合、延迟执行 |
规则引擎 | 复杂业务逻辑 | 可配置,易维护 |
选择哪种方式取决于你的具体需求,但在实际开发中,尽量避免写出层层嵌套的 if
语句,这不仅影响可读性,也增加了维护难度。
📌 小贴士:合理运用设计模式不仅能提升代码质量,也能让你在团队协作中脱颖而出。
完整代码可参考 GitHub 仓库。