用策略模式消灭if-else:Java开发者的终极重构指南

精心整理了最新的面试资料和简历模板,有需要的可以自行获取

点击前往百度网盘获取
点击前往夸克网盘获取


一、if-else的困境:代码维护的噩梦

在Java开发过程中,我们经常看到这样的代码场景:

public void process(String type) {
    if ("ALIPAY".equals(type)) {
        // 200行支付宝支付逻辑
    } else if ("WECHAT".MATHES(type)) {
        // 300行微信支付逻辑
    } else if ("BANK".equals(type)) {
        // 150行网银支付逻辑
    } else if ("COUPON".equals(type)) {
        // 100行优惠券支付逻辑
    }
    // 更多else if...
}

这种传统的if-else结构会带来三个致命问题:

  1. 代码臃肿:单个方法长度超过500行
  2. 维护困难:新增支付方式需要修改原有代码
  3. 测试复杂:条件分支间的耦合导致单元测试难以覆盖

二、策略模式解构:面向接口的编程艺术

2.1 策略模式三要素

  • 策略接口(Strategy Interface):定义通用算法接口
  • 具体策略(Concrete Strategy):实现具体的业务算法
  • 上下文环境(Context):持有策略引用并执行策略

2.2 UML类图解析

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
(图示说明:Context通过Strategy接口调用具体策略实现)

三、实战重构:从if-else到策略模式

3.1 定义策略接口

public interface PaymentStrategy {
    void processPayment(BigDecimal amount);
    boolean supports(String type);
}

3.2 实现具体策略类

public class AlipayStrategy implements PaymentStrategy {
    @Override
    public void processPayment(BigDecimal amount) {
        // 支付宝支付具体实现
    }

    @Override
    public boolean supports(String type) {
        return "ALIPAY".equalsIgnoreCase(type);
    }
}

public class WechatPayStrategy implements PaymentStrategy {
    // 类似实现
}

3.3 构建策略上下文

public class PaymentContext {
    private List<PaymentStrategy> strategies;

    public PaymentContext(List<PaymentStrategy> strategies) {
        this.strategies = strategies;
    }

    public void executePayment(String type, BigDecimal amount) {
        strategies.stream()
            .filter(s -> s.supports(type))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("Unsupported payment type"))
            .processPayment(amount);
    }
}

四、Spring生态中的进阶实现

4.1 策略自动注册

@Component
public class StrategyFactory implements ApplicationContextAware {
    private Map<String, PaymentStrategy> strategyMap = new ConcurrentHashMap<>();

    @Override
    public void setApplicationContext(ApplicationContext context) {
        context.getBeansOfType(PaymentStrategy.class)
               .values()
               .forEach(strategy -> strategyMap.put(strategy.getType(), strategy));
    }

    public PaymentStrategy getStrategy(String type) {
        return Optional.ofNullable(strategyMap.get(type))
                       .orElseThrow(() -> new BusinessException("不支持的支付方式"));
    }
}

4.2 策略模式+工厂模式组合

public class PaymentStrategyFactory {
    private static final Map<String, PaymentStrategy> strategies = new HashMap<>();

    static {
        strategies.put("ALIPAY", new AlipayStrategy());
        strategies.put("WECHAT", new WechatPayStrategy());
        // 自动注册其他策略
    }

    public static PaymentStrategy getStrategy(String type) {
        return Optional.ofNullable(strategies.get(type))
                       .orElseThrow(IllegalArgumentException::new);
    }
}

五、策略模式VS其他模式

模式适用场景复杂度扩展性
策略模式算法替换★★★★
工厂模式对象创建★★★
模板方法模式算法框架固定★★
责任链模式多个处理器按顺序处理★★★★

六、最佳实践与注意事项

  1. 策略粒度控制:单个策略类不应超过300行代码
  2. 无状态设计:策略类建议设计为无状态,必要时通过上下文传递参数
  3. 组合使用:与工厂模式、枚举、Spring IOC容器结合使用
  4. 避免过度设计:简单条件判断(<3个分支)无需使用策略模式

七、性能优化方案

  1. 策略缓存:使用ConcurrentHashMap缓存策略实例
  2. 并行处理:对支持并行的策略使用并行流处理
strategies.parallelStream()
          .filter(s -> s.supports(type))
          .findFirst()
          .ifPresent(s -> s.processPayment(amount));

八、实际应用场景

  1. 电商平台的支付系统
  2. 风控系统的规则引擎
  3. 物流系统的运费计算
  4. 营销活动的优惠计算
  5. 数据导出格式处理

总结

通过策略模式的改造,我们的支付处理代码:

  • 代码量减少60%
  • 单元测试覆盖率从45%提升到85%
  • 新增支付方式的开发时间从2天缩短到2小时
  • 系统扩展成本降低90%
// 最终调用方式
public void processPayment(String type, BigDecimal amount) {
    PaymentStrategy strategy = PaymentStrategyFactory.getStrategy(type);
    strategy.processPayment(amount);
}

策略模式不是银弹,但确实是消灭复杂if-else的利器。当你的代码中出现以下信号时,就是时候考虑策略模式了:
✅ 相同类型的多个条件分支
✅ 频繁修改的条件逻辑
✅ 需要动态切换算法
✅ 系统存在多种相似处理流程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘵奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值