《别再写满屏的if-else了!Spring Boot + 策略模式实战优化》

《别再写满屏的if-else了!Spring Boot + 策略模式实战优化》

哈喽,小伙伴们!今天我们来聊聊一个让很多程序员头疼的问题------满屏幕的if-else语句。相信大家都见过那种一个方法里嵌套了十几层if-else的代码吧?不仅难维护,新加一个条件还得小心翼翼。今天我就给大家带来一个超实用的解决方案:Spring Boot + 策略模式实战优化!

一、问题场景:支付业务中的if-else地狱

假设我们有个电商系统,需要支持多种支付方式:支付宝、微信支付、银联支付。很多同学可能会这样写:

csharp 复制代码
@Service
public class PaymentService {
    
    public String pay(String payType, BigDecimal amount) {
        if ("alipay".equals(payType)) {
            // 支付宝支付
            System.out.println("使用支付宝支付:" + amount);
            return "支付宝支付成功";
        } else if ("wechat".equals(payType)) {
            // 微信支付
            System.out.println("使用微信支付:" + amount);
            return "微信支付成功";
        } else if ("unionpay".equals(payType)) {
            // 银联支付
            System.out.println("使用银联支付:" + amount);
            return "银联支付成功";
        } else {
            throw new RuntimeException("支付方式错误");
        }
    }
}

看起来是不是很熟悉?如果再加个"云闪付"、"数字货币支付",这个方法就会越来越臃肿!

二、策略模式登场:优雅解决方案

2.1 什么是策略模式?

简单说,策略模式就是定义一系列算法,把它们封装起来,并且使它们可以相互替换。这样,算法的变化就不会影响到使用算法的客户端。

2.2 三步改造法

第一步:定义策略接口
arduino 复制代码
public interface PaymentStrategy {
    /**
     * 支付类型
     */
    String getType();
    
    /**
     * 支付方法
     */
    String pay(BigDecimal amount);
}
第二步:实现具体策略
typescript 复制代码
@Component
public class AlipayStrategy implements PaymentStrategy {
    
    @Override
    public String getType() {
        return "alipay";
    }
    
    @Override
    public String pay(BigDecimal amount) {
        // 这里写真实的支付宝支付逻辑
        System.out.println("执行支付宝支付,金额:" + amount);
        return "支付宝支付成功,金额:" + amount;
    }
}
​
@Component
public class WechatPayStrategy implements PaymentStrategy {
    
    @Override
    public String getType() {
        return "wechat";
    }
    
    @Override
    public String pay(BigDecimal amount) {
        // 微信支付逻辑
        System.out.println("执行微信支付,金额:" + amount);
        return "微信支付成功,金额:" + amount;
    }
}
​
@Component
public class UnionPayStrategy implements PaymentStrategy {
    
    @Override
    public String getType() {
        return "unionpay";
    }
    
    @Override
    public String pay(BigDecimal amount) {
        // 银联支付逻辑
        System.out.println("执行银联支付,金额:" + amount);
        return "银联支付成功,金额:" + amount;
    }
}
第三步:策略工厂类
typescript 复制代码
@Component
public class PaymentStrategyFactory {
    
    private final Map<String, PaymentStrategy> strategyMap = new ConcurrentHashMap<>();
    
    /**
     * 注入所有PaymentStrategy实现
     */
    public PaymentStrategyFactory(List<PaymentStrategy> strategies) {
        for (PaymentStrategy strategy : strategies) {
            strategyMap.put(strategy.getType(), strategy);
        }
    }
    
    /**
     * 获取支付策略
     */
    public PaymentStrategy getStrategy(String type) {
        PaymentStrategy strategy = strategyMap.get(type);
        if (strategy == null) {
            throw new RuntimeException("未找到对应的支付策略:" + type);
        }
        return strategy;
    }
    
    /**
     * 获取所有支持的支付方式
     */
    public Set<String> getSupportTypes() {
        return strategyMap.keySet();
    }
}

三、使用姿势:简洁优雅的调用

3.1 改造后的Service

typescript 复制代码
@Service
public class PaymentService {
    
    private final PaymentStrategyFactory strategyFactory;
    
    public PaymentService(PaymentStrategyFactory strategyFactory) {
        this.strategyFactory = strategyFactory;
    }
    
    public String pay(String payType, BigDecimal amount) {
        PaymentStrategy strategy = strategyFactory.getStrategy(payType);
        return strategy.pay(amount);
    }
    
    /**
     * 获取支持的支付方式
     */
    public Set<String> getSupportPayTypes() {
        return strategyFactory.getSupportTypes();
    }
}

3.2 Controller层示例

less 复制代码
@RestController
@RequestMapping("/api/payment")
public class PaymentController {
    
    private final PaymentService paymentService;
    
    public PaymentController(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
    
    @PostMapping("/pay")
    public ResponseEntity<?> pay(@RequestParam String payType, 
                                @RequestParam BigDecimal amount) {
        try {
            String result = paymentService.pay(payType, amount);
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }
    
    @GetMapping("/support-types")
    public ResponseEntity<?> getSupportTypes() {
        return ResponseEntity.ok(paymentService.getSupportPayTypes());
    }
}

四、进阶玩法:注解 + 策略模式

如果你想要更优雅,可以试试注解方式:

4.1 定义支付类型注解

less 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface PayType {
    String value();
}

4.2 改造策略实现

less 复制代码
@PayType("alipay")
public class AlipayStrategy implements PaymentStrategy {
    // 省略具体实现
}
​
@PayType("wechat")
public class WechatPayStrategy implements PaymentStrategy {
    // 省略具体实现
}

4.3 改造工厂类

kotlin 复制代码
@Component
public class PaymentStrategyFactoryV2 {
    
    private final Map<String, PaymentStrategy> strategyMap = new ConcurrentHashMap<>();
    
    /**
     * 使用ApplicationContext获取所有带PayType注解的Bean
     */
    public PaymentStrategyFactoryV2(ApplicationContext applicationContext) {
        Map<String, Object> beans = applicationContext.getBeansWithAnnotation(PayType.class);
        
        beans.forEach((beanName, bean) -> {
            PayType annotation = applicationContext.findAnnotationOnBean(beanName, PayType.class);
            if (annotation != null && bean instanceof PaymentStrategy) {
                strategyMap.put(annotation.value(), (PaymentStrategy) bean);
            }
        });
    }
    
    // 其他方法保持不变
}

五、测试验证

创建一个测试类验证一下:

java

csharp 复制代码
@SpringBootTest
class PaymentStrategyTest {
    
    @Autowired
    private PaymentService paymentService;
    
    @Test
    void testPay() {
        BigDecimal amount = new BigDecimal("100.50");
        
        System.out.println("支持的支付方式:" + paymentService.getSupportPayTypes());
        
        String result = paymentService.pay("alipay", amount);
        System.out.println("支付结果:" + result);
        
        result = paymentService.pay("wechat", amount);
        System.out.println("支付结果:" + result);
        
        // 测试不存在的支付方式
        assertThrows(RuntimeException.class, () -> {
            paymentService.pay("unknown", amount);
        });
    }
}

六、实际应用扩展

6.1 结合配置文件动态启用策略

markdown 复制代码
# application.yml
payment:
  enabled-strategies:
    - alipay
    - wechat
    - unionpay
swift 复制代码
@Component
public class DynamicPaymentStrategyFactory {
    
    @Value("${payment.enabled-strategies}")
    private List<String> enabledStrategies;
    
    private final Map<String, PaymentStrategy> strategyMap = new ConcurrentHashMap<>();
    
    public DynamicPaymentStrategyFactory(List<PaymentStrategy> strategies) {
        for (PaymentStrategy strategy : strategies) {
            if (enabledStrategies.contains(strategy.getType())) {
                strategyMap.put(strategy.getType(), strategy);
            }
        }
    }
    
    // 其他方法...
}

6.2 策略模式+模板方法模式组合

typescript 复制代码
public abstract class AbstractPaymentStrategy implements PaymentStrategy {
    
    @Override
    public String pay(BigDecimal amount) {
        // 1. 参数验证
        validate(amount);
        
        // 2. 执行支付
        String transactionId = doPay(amount);
        
        // 3. 记录日志
        logPayment(transactionId, amount);
        
        // 4. 返回结果
        return buildResult(transactionId, amount);
    }
    
    protected abstract String doPay(BigDecimal amount);
    
    protected void validate(BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new RuntimeException("支付金额必须大于0");
        }
    }
    
    protected void logPayment(String transactionId, BigDecimal amount) {
        System.out.println("支付流水号:" + transactionId + ",金额:" + amount);
    }
    
    protected String buildResult(String transactionId, BigDecimal amount) {
        return getType() + "支付成功,流水号:" + transactionId + ",金额:" + amount;
    }
}

总结

优点总结:

  1. 开闭原则:新增支付方式只需添加新策略类,无需修改现有代码
  2. 可读性:代码结构清晰,职责分明
  3. 可维护性:每个支付逻辑独立,方便测试和修改
  4. 可扩展性:轻松支持动态配置、热更新等高级功能

使用场景:

  • 多种相似算法或业务逻辑需要切换
  • 存在大量的条件判断语句
  • 系统需要动态选择不同算法
  • 希望避免使用多重条件转移语句

注意事项:

  1. 策略数量控制:如果策略类过多,考虑使用其他模式(如责任链模式)组合使用
  2. 客户端感知:客户端需要知道所有策略,可以通过配置中心或枚举管理
  3. 性能考虑:策略模式会增加对象数量,在极端性能敏感场景需要权衡
  4. Spring集成:确保策略类都被Spring管理,注意Bean的加载顺序
  5. 默认策略:考虑提供一个默认策略,避免因策略不存在而报错
  6. 策略参数:如果不同策略需要不同参数,可以考虑使用Context对象封装

最后的小贴士:

策略模式不是银弹,如果你的业务逻辑很简单,只有2-3个分支,那么简单的if-else可能更合适。但是当分支超过3个,或者未来可能会增加更多分支时,策略模式的优势就会体现出来。

记住,好的代码不是一蹴而就的,而是在不断重构中逐渐变好的。当你看到满屏的if-else时,不妨想想:这里是不是可以用策略模式优化一下?

希望这篇博客能帮到你!如果有问题或更好的建议,欢迎在评论区交流讨论。我们一起写出更优雅的代码!


作者:张工摆Bug 转载请注明出处,让我们一起打造更好的技术社区!

相关推荐
言慢行善21 小时前
sqlserver模糊查询问题
java·数据库·sqlserver
专吃海绵宝宝菠萝屋的派大星21 小时前
使用Dify对接自己开发的mcp
java·服务器·前端
大数据新鸟1 天前
操作系统之虚拟内存
java·服务器·网络
Tong Z1 天前
常见的限流算法和实现原理
java·开发语言
凭君语未可1 天前
Java 中的实现类是什么
java·开发语言
He少年1 天前
【基础知识、Skill、Rules和MCP案例介绍】
java·前端·python
克里斯蒂亚诺更新1 天前
myeclipse的pojie
java·ide·myeclipse
迷藏4941 天前
**eBPF实战进阶:从零构建网络流量监控与过滤系统**在现代云原生架构中,**网络可观测性**和**安全隔离**已成为
java·网络·python·云原生·架构
迷藏4941 天前
**发散创新:基于Solid协议的Web3.0去中心化身份认证系统实战解析**在Web3.
java·python·web3·去中心化·区块链
qq_433502181 天前
Codex cli 飞书文档创建进阶实用命令 + Skill 创建&使用 小白完整教程
java·前端·飞书