关于if-else如何优化

35 阅读5分钟

在 Java 开发中,过多的if-else(尤其是嵌套或长链)会导致代码可读性差、维护成本高、扩展性低。以下是系统化的优化方案,从基础重构到设计模式,覆盖不同场景的解决方案:

一、先明确:哪些 if 值得优化?

并非所有if都要消除,以下场景优先优化:

  • 长链if-else if-else(超过 3 层);
  • 嵌套if(超过 2 层);
  • 频繁变更的条件判断(如业务规则、状态流转);
  • 重复的条件逻辑(多处出现相同判断)。

二、基础优化:重构现有 if 逻辑

1. 提前 return / 卫语句(消灭嵌套)

将嵌套的if拆解为 “前置判断 + 提前返回”,扁平化代码结构。

反例(嵌套 if)

public double calculatePrice(User user, Order order) {
    double price = order.getBasePrice();
    if (user.isVip()) {
        if (order.getAmount() > 1000) {
            price = price * 0.8; // VIP且金额>1000,8折
        } else {
            price = price * 0.9; // VIP且金额≤1000,9折
        }
    } else {
        price = price * 1.0; // 非VIP不打折
    }
    return price;
}

正例(卫语句)

public double calculatePrice(User user, Order order) {
    double price = order.getBasePrice();
    if (!user.isVip()) {
        return price; // 非VIP直接返回,消灭else
    }
    return order.getAmount() > 1000 ? price * 0.8 : price * 0.9;
}

2. 合并条件表达式(消除重复判断)

将逻辑上等价的多个条件合并,减少判断次数。

反例:行

if (order.getStatus() == 1 || order.getStatus() == 2 || order.getStatus() == 3) {
    // 处理已支付状态
}

正例

// 1. 用集合封装条件
private static final Set<Integer> PAID_STATUS = Set.of(1, 2, 3);
if (PAID_STATUS.contains(order.getStatus())) {
    // 处理已支付状态
}

// 2. 用枚举(更推荐,语义化)
enum OrderStatus {
    UNPAID(0), PAID(1), SHIPPED(2), RECEIVED(3);
    private final int code;
    // 构造器+getter
    public static boolean isPaid(OrderStatus status) {
        return status == PAID || status == SHIPPED || status == RECEIVED;
    }
}
if (OrderStatus.isPaid(order.getStatus())) {
    // 处理已支付状态
}

3. 用三元运算符 / Optional 简化简单判断

适用于 “二选一” 的简单逻辑,替代短if-else

示例 1(三元运算符) :运行

// 反例
String tip;
if (user.getAge() < 18) {
    tip = "未成年";
} else {
    tip = "成年";
}

// 正例
String tip = user.getAge() < 18 ? "未成年" : "成年";

示例 2(Optional 避免空判断)

// 反例
if (user != null) {
    if (user.getAddress() != null) {
        return user.getAddress().getCity();
    }
}
return "未知";

// 正例
return Optional.ofNullable(user)
               .map(User::getAddress)
               .map(Address::getCity)
               .orElse("未知");

三、进阶优化:用数据结构替代 if

1. 映射表(Map):处理 “键 - 逻辑” 映射

适用于根据固定值(如类型、状态)执行不同逻辑的场景,替代if-else if

场景:根据支付类型(微信、支付宝、银行卡)计算手续费。

反例:运行

public double calculateFee(String payType, double amount) {
    if ("WECHAT".equals(payType)) {
        return amount * 0.006;
    } else if ("ALIPAY".equals(payType)) {
        return amount * 0.005;
    } else if ("BANK".equals(payType)) {
        return amount * 0.008;
    }
    throw new IllegalArgumentException("无效支付类型");
}

正例(Map + 函数式接口)

// 1. 定义手续费计算函数
@FunctionalInterface
interface FeeCalculator {
    double calculate(double amount);
}

// 2. 初始化映射表(静态常量,仅加载一次)
private static final Map<String, FeeCalculator> FEE_MAP = new HashMap<>();
static {
    FEE_MAP.put("WECHAT", amount -> amount * 0.006);
    FEE_MAP.put("ALIPAY", amount -> amount * 0.005);
    FEE_MAP.put("BANK", amount -> amount * 0.008);
}

// 3. 简化判断逻辑
public double calculateFee(String payType, double amount) {
    FeeCalculator calculator = FEE_MAP.get(payType);
    if (calculator == null) {
        throw new IllegalArgumentException("无效支付类型");
    }
    return calculator.calculate(amount);
}

2. 枚举:封装状态 / 类型 + 行为

枚举不仅能替代 “值判断”,还能直接封装对应逻辑,比 Map 更类型安全。

场景:同上(支付类型计算手续费),用枚举优化:运行

// 1. 定义枚举,封装行为
enum PayType {
    WECHAT(0.006) {
        @Override
        public double calculateFee(double amount) {
            return amount * this.rate;
        }
    },
    ALIPAY(0.005) {
        @Override
        public double calculateFee(double amount) {
            return amount * this.rate;
        }
    },
    BANK(0.008) {
        @Override
        public double calculateFee(double amount) {
            return amount * this.rate;
        }
    };

    protected final double rate;

    PayType(double rate) {
        this.rate = rate;
    }

    // 抽象方法,强制每个枚举值实现
    public abstract double calculateFee(double amount);

    // 辅助方法:根据字符串获取枚举(避免外部判断)
    public static PayType from(String payType) {
        return PayType.valueOf(payType.toUpperCase());
    }
}

// 2. 业务逻辑简化为一行
public double calculateFee(String payType, double amount) {
    return PayType.from(payType).calculateFee(amount);
}

四、架构级优化:设计模式

1. 策略模式(Strategy):动态切换算法

适用于 “同一行为有多种实现方式” 的场景(如排序、支付、折扣计算),完全消除条件判断,且易于扩展。

核心结构

  • 抽象策略(Strategy):定义统一接口;
  • 具体策略(ConcreteStrategy):实现不同逻辑;
  • 上下文(Context):接收策略并执行。

示例(折扣计算) :运行

// 1. 抽象策略
interface DiscountStrategy {
    double apply(double amount);
}

// 2. 具体策略
class VipDiscount implements DiscountStrategy {
    @Override
    public double apply(double amount) {
        return amount * 0.8;
    }
}

class NewUserDiscount implements DiscountStrategy {
    @Override
    public double apply(double amount) {
        return amount * 0.9;
    }
}

class NoDiscount implements DiscountStrategy {
    @Override
    public double apply(double amount) {
        return amount;
    }
}

// 3. 上下文(可选,封装策略选择逻辑)
class DiscountContext {
    private DiscountStrategy strategy;

    // 动态设置策略
    public void setStrategy(DiscountStrategy strategy) {
        this.strategy = strategy;
    }

    // 执行策略
    public double calculate(double amount) {
        return strategy.apply(amount);
    }
}

// 4. 业务调用(无if)
public void processOrder(User user, double amount) {
    DiscountContext context = new DiscountContext();
    if (user.isVip()) {
        context.setStrategy(new VipDiscount()); // 仅此处少量判断,可结合工厂模式消除
    } else if (user.isNewUser()) {
        context.setStrategy(new NewUserDiscount());
    } else {
        context.setStrategy(new NoDiscount());
    }
    double finalAmount = context.calculate(amount);
}

2. 工厂模式(Factory):配合策略模式消除策略选择的 if

结合工厂模式,可彻底消除 “选择策略” 的if:运行

// 1. 策略工厂
class DiscountFactory {
    public static DiscountStrategy getStrategy(User user) {
        if (user.isVip()) {
            return new VipDiscount();
        } else if (user.isNewUser()) {
            return new NewUserDiscount();
        }
        return new NoDiscount();
    }
}

// 2. 业务调用(完全无if)
public void processOrder(User user, double amount) {
    DiscountStrategy strategy = DiscountFactory.getStrategy(user);
    double finalAmount = strategy.apply(amount);
}

3. 状态模式(State):处理状态流转的 if

适用于 “对象状态决定行为” 的场景(如订单状态:待支付→已支付→已发货→已完成),替代大量状态判断的if

核心思想:将每个状态的行为封装为独立类,状态切换由状态类自身控制。

五、其他补充技巧

  1. 使用多态:父类定义抽象方法,子类实现不同逻辑,通过多态调用替代if判断(本质是策略模式的简化)。
  2. 提取方法:将复杂if内的逻辑提取为独立方法,即使if仍存在,代码可读性也会提升。
  3. 避免过度优化:简单的、不变的if(如 2 层以内)无需强制消除,可读性优先。
  4. 使用规则引擎:超复杂的业务规则(如风控、优惠券)可引入规则引擎(如 Drools),彻底脱离硬编码的if