在代码审查时,我们经常看到这样的场景:一个方法里嵌套了七八层 if/else,就像俄罗斯套娃一样。上周我review一个订单状态处理的代码,光是判断各种优惠条件就用了12个if嵌套,看得人头皮发麻。这种代码有三个致命问题:
去年我们系统有个线上事故,就是因为某个边缘条件的if判断被错误嵌套,导致百万级优惠券被错误核销。事后用SonarQube扫描,那个方法的圈复杂度高达48(建议值不超过10)。
这是我最推荐的入门级优化方案。把异常条件提前返回,避免箭头型代码。看个电商例子:
java复制// 优化前
public void processOrder(Order order) {
if (order != null) {
if (order.isValid()) {
if (order.getItems() != null) {
// 真实业务逻辑
} else {
throw new IllegalArgumentException("Empty items");
}
} else {
throw new IllegalArgumentException("Invalid order");
}
}
}
// 优化后
public void processOrder(Order order) {
if (order == null) throw new IllegalArgumentException("Null order");
if (!order.isValid()) throw new IllegalArgumentException("Invalid order");
if (order.getItems() == null) throw new IllegalArgumentException("Empty items");
// 真实业务逻辑
}
适用场景:
实测效果:
当遇到根据不同类型执行不同行为时,这个模式就是救星。比如支付方式处理:
java复制// 定义策略接口
interface PaymentStrategy {
void process(PaymentRequest request);
}
// 具体策略实现
class AlipayStrategy implements PaymentStrategy {
@Override
public void process(PaymentRequest request) {
// 支付宝特有逻辑
}
}
class WechatPayStrategy implements PaymentStrategy {
@Override
public void process(PaymentRequest request) {
// 微信支付特有逻辑
}
}
// 策略上下文
class PaymentContext {
private static final Map<String, PaymentStrategy> strategies = Map.of(
"alipay", new AlipayStrategy(),
"wechat", new WechatPayStrategy()
);
public void processPayment(String type, PaymentRequest request) {
PaymentStrategy strategy = strategies.get(type);
if (strategy == null) throw new IllegalArgumentException("Unsupported type");
strategy.process(request);
}
}
优势对比:
| 指标 | if/else实现 | 策略模式 |
|---|---|---|
| 新增支付方式 | 修改原方法 | 新增类即可 |
| 单测复杂度 | 高 | 低 |
| 编译时检查 | 无 | 有 |
对于订单状态流转这种场景,状态模式比if/else强十倍。看这个订单案例:
java复制// 状态接口
interface OrderState {
void next(Order order);
void prev(Order order);
}
// 具体状态
class PendingState implements OrderState {
public void next(Order order) {
order.setState(new PaidState());
}
//...其他方法
}
class PaidState implements OrderState {
public void next(Order order) {
order.setState(new ShippedState());
}
//...其他方法
}
// 上下文类
class Order {
private OrderState state;
public void nextState() {
state.next(this);
}
//...其他方法
}
避坑指南:
适合需要多个校验器依次处理的场景,比如风控审核流程:
java复制abstract class RiskHandler {
protected RiskHandler next;
public RiskHandler linkWith(RiskHandler next) {
this.next = next;
return next;
}
public abstract boolean check(User user);
protected boolean checkNext(User user) {
return next == null || next.check(user);
}
}
// 具体处理器
class CreditHandler extends RiskHandler {
public boolean check(User user) {
if (user.getCreditScore() < 600) return false;
return checkNext(user);
}
}
class BlacklistHandler extends RiskHandler {
public boolean check(User user) {
if (user.isInBlacklist()) return false;
return checkNext(user);
}
}
// 使用方式
RiskHandler chain = new CreditHandler()
.linkWith(new BlacklistHandler());
boolean passed = chain.check(user);
性能优化技巧:
遇到复杂条件判断时,可以用这个决策树选择合适方案:
code复制是否处理多种类型行为?
├─ 是 → 策略模式
└─ 否 →
是否涉及状态流转?
├─ 是 → 状态模式
└─ 否 →
是否需要多个校验器?
├─ 是 → 责任链
└─ 否 → 卫语句
在我们电商系统中,一个完整的订单创建流程实际上混合使用了多种模式:
java复制public OrderResult createOrder(OrderRequest request) {
// 卫语句校验
if (request == null) throw new IllegalArgumentException();
if (request.getItems().isEmpty()) throw new IllegalArgumentException();
// 责任链检查
if (!inventoryChain.check(request)) return fail("库存不足");
// 策略模式计算优惠
DiscountStrategy strategy = strategyFactory.get(request.getCouponType());
DiscountResult discount = strategy.calculate(request);
// 状态模式初始化订单
Order order = new Order();
order.setState(new PendingState());
// ...其他逻辑
}
虽然这些模式能提升代码质量,但也要注意:
实测数据(基于JMH基准测试):
| 模式 | 吞吐量 (ops/ms) | 内存分配 (B/op) |
|---|---|---|
| 原始if/else | 1254 | 0 |
| 策略模式 | 983 | 16 |
| 状态模式 | 845 | 24 |
| 责任链 | 672 | 32 |
建议在复杂业务逻辑中使用这些模式,简单判断仍可用if/else。我们团队的经验法则是:当某个方法的if/else超过3层,或者同类判断在多个地方重复出现时,就应该考虑重构。
渐进式重构:
测试保障:
IDE神器:
最近在重构一个物流运费计算模块时,我把57个if/else判断重构成了策略模式+责任链,不仅代码量减少了35%,而且新增运输方式的时间从2天缩短到2小时。更惊喜的是,由于逻辑清晰了,我们发现了3处隐藏的计算错误,每年能节省百万级运费成本。