前言:为什么我们要避免if-else嵌套?
在Java开发中,我们经常遇到这样的代码:
public double calculatePrice(String userType, int age, double amount) {
if ("VIP".equals(userType)) {
if (age > 60) {
return amount * 0.7; // VIP且老年
} else if (age < 18) {
return amount * 0.8; // VIP且未成年
} else {
return amount * 0.9; // VIP普通
}
} else if ("NORMAL".equals(userType)) {
if (age > 60) {
return amount * 0.8; // 普通用户老年
} else if (age < 18) {
return amount * 0.9; // 普通用户未成年
} else {
return amount; // 普通用户
}
} else {
return amount; // 其他情况
}
}
这种代码通常被称为"箭头代码",它存在以下几个问题:
-
可读性差:逻辑嵌套太深,难以理解
-
维护困难:添加新条件时需要修改原有方法
-
违反开闭原则:对扩展开放,对修改关闭
-
测试复杂:需要覆盖多种条件组合
让我们通过几种设计模式和编程技巧来解决这个问题。
方法一:使用策略模式(Strategy Pattern)
适用场景
当根据不同的类型需要执行不同算法时。
实现步骤
定义策略接口
public interface DiscountStrategy {
double calculate(double amount);
}
2.实现具体策略类
// VIP策略
public class VipDiscountStrategy implements DiscountStrategy {
@Override
public double calculate(double amount) {
return amount * 0.9;
}
}
// 老年VIP策略
public class ElderVipDiscountStrategy implements DiscountStrategy {
@Override
public double calculate(double amount) {
return amount * 0.7;
}
}
// 普通用户策略
public class NormalDiscountStrategy implements DiscountStrategy {
@Override
public double calculate(double amount) {
return amount;
}
}
3.创建策略工厂
public class DiscountStrategyFactory {
private static Map<String, DiscountStrategy> strategies = new HashMap<>();
static {
strategies.put("VIP_YOUNG", new VipDiscountStrategy());
strategies.put("VIP_ELDER", new ElderVipDiscountStrategy());
strategies.put("NORMAL", new NormalDiscountStrategy());
// 可以轻松添加新策略
}
public static DiscountStrategy getStrategy(String userType, int age) {
String key = buildKey(userType, age);
return strategies.getOrDefault(key, new NormalDiscountStrategy());
}
private static String buildKey(String userType, int age) {
if ("VIP".equals(userType)) {
return age > 60 ? "VIP_ELDER" : "VIP_YOUNG";
}
return "NORMAL";
}
}
4.使用策略模式
public double calculatePrice(String userType, int age, double amount) {
DiscountStrategy strategy = DiscountStrategyFactory.getStrategy(userType, age);
return strategy.calculate(amount);
}
方法二:使用枚举(Enum)
适用场景
当条件相对简单且固定时。
实现示例
public enum UserType {
VIP(0.1) {
@Override
public double applyDiscount(double amount, int age) {
double baseDiscount = super.applyDiscount(amount, age);
if (age > 60) {
return baseDiscount * 0.7;
}
return baseDiscount;
}
},
NORMAL(0.0) {
@Override
public double applyDiscount(double amount, int age) {
if (age > 60) {
return amount * 0.8;
}
return amount;
}
};
private final double discountRate;
UserType(double discountRate) {
this.discountRate = discountRate;
}
public double applyDiscount(double amount, int age) {
return amount * (1 - discountRate);
}
}
方法三:使用Java 8+
使用Java 8+的函数式编程
使用Map + Function
public class DiscountCalculator {
private static Map<String, Function<Double, Double>> discountMap = new HashMap<>();
static {
discountMap.put("VIP", amount -> amount * 0.9);
discountMap.put("NORMAL", amount -> amount);
discountMap.put("ELDER", amount -> amount * 0.8);
}
public double calculate(String type, double amount) {
return discountMap.getOrDefault(type, a -> a).apply(amount);
}
}
使用Predicate进行条件判断
public class ConditionalDiscount {
private List<DiscountCondition> conditions = new ArrayList<>();
public ConditionalDiscount() {
// 按优先级添加条件
conditions.add(new DiscountCondition(
(user, age) -> "VIP".equals(user) && age > 60,
amount -> amount * 0.7
));
conditions.add(new DiscountCondition(
(user, age) -> "VIP".equals(user) && age < 18,
amount -> amount * 0.8
));
conditions.add(new DiscountCondition(
(user, age) -> "VIP".equals(user),
amount -> amount * 0.9
));
}
public double calculate(String userType, int age, double amount) {
return conditions.stream()
.filter(condition -> condition.test(userType, age))
.findFirst()
.map(condition -> condition.apply(amount))
.orElse(amount);
}
private static class DiscountCondition {
private final BiPredicate<String, Integer> predicate;
private final Function<Double, Double> discount;
public DiscountCondition(BiPredicate<String, Integer> predicate,
Function<Double, Double> discount) {
this.predicate = predicate;
this.discount = discount;
}
public boolean test(String userType, int age) {
return predicate.test(userType, age);
}
public double apply(double amount) {
return discount.apply(amount);
}
}
}
通过本文介绍的几种方法,我们可以有效地减少Java代码中的if-else嵌套:
方法 适用场景 优点
策略模式 复杂算法选择 易于扩展,符合开闭原则
枚举 简单固定条件 代码清晰,类型安全
函数式编程 动态条件 灵活,代码简洁
状态模式 状态驱动行为 状态转换清晰
记住,我们的目标不是完全消除if-else,而是让代码更加:
- 可读性强
- 易于维护
- 便于测试
- 支持扩展
2630

被折叠的 条评论
为什么被折叠?



