别再写 if-else 了:策略模式 + 枚举让你的代码优雅 10 倍

引言

你是不是经常写这样的代码?

if (paymentType == "WECHAT") {
    // 微信支付逻辑
} else if (paymentType == "ALIPAY") {
    // 支付宝支付逻辑
} else if (paymentType == "BANK_CARD") {
    // 银行卡支付逻辑
} else {
    throw new IllegalArgumentException("不支持的支付方式");
}

这种代码的问题很明显:

  • 违反开闭原则:每次新增支付方式都要修改原有代码
  • 代码臃肿:支付方式越多,if-else 链条越长
  • 难以测试:每个分支都需要单独测试
  • 可读性差:逻辑分散在各个分支中

本文将介绍一种优雅的解决方案:策略模式 + 枚举,让你的代码告别 if-else,变得清晰、可扩展、易于维护。


一、传统 if-else 写法

让我们先看看传统写法的完整示例:

1.1 支付订单类

public class PaymentOrder {
    private String orderId;
    private BigDecimal amount;
    private String paymentType;
    private String tradeNo;
    
    // 省略 getter/setter
}

1.2 支付服务(传统写法)

@Service
public class PaymentService {
    
    @Autowired
    private WechatPayClient wechatPayClient;
    
    @Autowired
    private AlipayClient alipayClient;
    
    @Autowired
    private BankCardClient bankCardClient;
    
    public PaymentResult pay(PaymentOrder order) {
        if ("WECHAT".equals(order.getPaymentType())) {
            // 微信支付逻辑
            WechatPayRequest request = new WechatPayRequest();
            request.setOrderId(order.getOrderId());
            request.setAmount(order.getAmount());
            request.setOpenId(order.getOpenId());
            
            try {
                return wechatPayClient.pay(request);
            } catch (WechatPayException e) {
                throw new PaymentException("微信支付失败", e);
            }
            
        } else if ("ALIPAY".equals(order.getPaymentType())) {
            // 支付宝支付逻辑
            AlipayRequest request = new AlipayRequest();
            request.setOrderId(order.getOrderId());
            request.setAmount(order.getAmount());
            request.setUserId(order.getUserId());
            
            try {
                return alipayClient.pay(request);
            } catch (AlipayException e) {
                throw new PaymentException("支付宝支付失败", e);
            }
            
        } else if ("BANK_CARD".equals(order.getPaymentType())) {
            // 银行卡支付逻辑
            BankCardRequest request = new BankCardRequest();
            request.setOrderId(order.getOrderId());
            request.setAmount(order.getAmount());
            request.setCardNo(order.getCardNo());
            request.setValidDate(order.getValidDate());
            
            try {
                return bankCardClient.pay(request);
            } catch (BankCardException e) {
                throw new PaymentException("银行卡支付失败", e);
            }
            
        } else {
            throw new IllegalArgumentException("不支持的支付方式: " + order.getPaymentType());
        }
    }
}

1.3 问题分析

问题表现影响
违反开闭原则新增支付方式需要修改 pay() 方法容易引入 bug,影响现有功能
代码臃肿每个支付方式的逻辑都写在一个方法里方法过长,难以阅读和维护
职责不清支付服务承担了所有支付方式的逻辑违反单一职责原则
难以测试需要在一个测试类中测试所有支付方式测试用例复杂,耦合度高

二、策略模式 + 枚举重构

2.1 定义策略接口

public interface PaymentStrategy {
    
    String getPaymentType();
    
    PaymentResult pay(PaymentOrder order);
}

2.2 实现具体策略

微信支付策略

@Component
public class WechatPaymentStrategy implements PaymentStrategy {
    
    @Autowired
    private WechatPayClient wechatPayClient;
    
    @Override
    public String getPaymentType() {
        return "WECHAT";
    }
    
    @Override
    public PaymentResult pay(PaymentOrder order) {
        WechatPayRequest request = new WechatPayRequest();
        request.setOrderId(order.getOrderId());
        request.setAmount(order.getAmount());
        request.setOpenId(order.getOpenId());
        
        try {
            return wechatPayClient.pay(request);
        } catch (WechatPayException e) {
            throw new PaymentException("微信支付失败", e);
        }
    }
}

支付宝支付策略

@Component
public class AlipayPaymentStrategy implements PaymentStrategy {
    
    @Autowired
    private AlipayClient alipayClient;
    
    @Override
    public String getPaymentType() {
        return "ALIPAY";
    }
    
    @Override
    public PaymentResult pay(PaymentOrder order) {
        AlipayRequest request = new AlipayRequest();
        request.setOrderId(order.getOrderId());
        request.setAmount(order.getAmount());
        request.setUserId(order.getUserId());
        
        try {
            return alipayClient.pay(request);
        } catch (AlipayException e) {
            throw new PaymentException("支付宝支付失败", e);
        }
    }
}

银行卡支付策略

@Component
public class BankCardPaymentStrategy implements PaymentStrategy {
    
    @Autowired
    private BankCardClient bankCardClient;
    
    @Override
    public String getPaymentType() {
        return "BANK_CARD";
    }
    
    @Override
    public PaymentResult pay(PaymentOrder order) {
        BankCardRequest request = new BankCardRequest();
        request.setOrderId(order.getOrderId());
        request.setAmount(order.getAmount());
        request.setCardNo(order.getCardNo());
        request.setValidDate(order.getValidDate());
        
        try {
            return bankCardClient.pay(request);
        } catch (BankCardException e) {
            throw new PaymentException("银行卡支付失败", e);
        }
    }
}

2.3 定义支付类型枚举

public enum PaymentType {
    
    WECHAT("WECHAT", "微信支付", WechatPaymentStrategy.class),
    ALIPAY("ALIPAY", "支付宝支付", AlipayPaymentStrategy.class),
    BANK_CARD("BANK_CARD", "银行卡支付", BankCardPaymentStrategy.class);
    
    private final String code;
    private final String description;
    private final Class<? extends PaymentStrategy> strategyClass;
    
    PaymentType(String code, String description, Class<? extends PaymentStrategy> strategyClass) {
        this.code = code;
        this.description = description;
        this.strategyClass = strategyClass;
    }
    
    public String getCode() {
        return code;
    }
    
    public String getDescription() {
        return description;
    }
    
    public Class<? extends PaymentStrategy> getStrategyClass() {
        return strategyClass;
    }
    
    public static PaymentType fromCode(String code) {
        for (PaymentType type : values()) {
            if (type.code.equals(code)) {
                return type;
            }
        }
        throw new IllegalArgumentException("不支持的支付方式: " + code);
    }
}

2.4 创建策略工厂

@Component
public class PaymentStrategyFactory {
    
    private final Map<String, PaymentStrategy> strategyMap = new ConcurrentHashMap<>();
    
    @Autowired
    public PaymentStrategyFactory(List<PaymentStrategy> strategies) {
        for (PaymentStrategy strategy : strategies) {
            strategyMap.put(strategy.getPaymentType(), strategy);
        }
    }
    
    public PaymentStrategy getStrategy(String paymentType) {
        PaymentStrategy strategy = strategyMap.get(paymentType);
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的支付方式: " + paymentType);
        }
        return strategy;
    }
    
    public PaymentStrategy getStrategy(PaymentType paymentType) {
        return getStrategy(paymentType.getCode());
    }
}

2.5 重构后的支付服务

@Service
public class PaymentService {
    
    @Autowired
    private PaymentStrategyFactory strategyFactory;
    
    public PaymentResult pay(PaymentOrder order) {
        PaymentStrategy strategy = strategyFactory.getStrategy(order.getPaymentType());
        return strategy.pay(order);
    }
}

2.6 调用方式

@RestController
@RequestMapping("/api/payment")
public class PaymentController {
    
    @Autowired
    private PaymentService paymentService;
    
    @PostMapping("/pay")
    public ResponseEntity<PaymentResult> pay(@RequestBody PaymentRequest request) {
        PaymentOrder order = PaymentOrder.builder()
            .orderId(request.getOrderId())
            .amount(request.getAmount())
            .paymentType(request.getPaymentType())
            .build();
        
        PaymentResult result = paymentService.pay(order);
        return ResponseEntity.ok(result);
    }
}

三、扩展新支付方式

现在,新增一种支付方式变得非常简单:

3.1 新增策略实现类

@Component
public class ApplePayPaymentStrategy implements PaymentStrategy {
    
    @Autowired
    private ApplePayClient applePayClient;
    
    @Override
    public String getPaymentType() {
        return "APPLE_PAY";
    }
    
    @Override
    public PaymentResult pay(PaymentOrder order) {
        ApplePayRequest request = new ApplePayRequest();
        request.setOrderId(order.getOrderId());
        request.setAmount(order.getAmount());
        request.setToken(order.getApplePayToken());
        
        try {
            return applePayClient.pay(request);
        } catch (ApplePayException e) {
            throw new PaymentException("Apple Pay 支付失败", e);
        }
    }
}

3.2 在枚举中注册

public enum PaymentType {
    WECHAT("WECHAT", "微信支付", WechatPaymentStrategy.class),
    ALIPAY("ALIPAY", "支付宝支付", AlipayPaymentStrategy.class),
    BANK_CARD("BANK_CARD", "银行卡支付", BankCardPaymentStrategy.class),
    APPLE_PAY("APPLE_PAY", "Apple Pay", ApplePayPaymentStrategy.class); // 新增
    
    // ... 其余代码不变
}

完成! 不需要修改任何现有代码,只需要新增两个文件:策略实现类和枚举值。


四、轻量级替代方案:Map + 函数式接口

如果觉得完整的策略模式过于复杂,可以使用 Map + 函数式接口的轻量级方案:

4.1 定义支付处理器

@FunctionalInterface
public interface PaymentHandler {
    PaymentResult handle(PaymentOrder order);
}

4.2 注册处理器

@Service
public class PaymentService {
    
    private final Map<String, PaymentHandler> handlerMap = new ConcurrentHashMap<>();
    
    @Autowired
    private WechatPayClient wechatPayClient;
    
    @Autowired
    private AlipayClient alipayClient;
    
    @Autowired
    private BankCardClient bankCardClient;
    
    @PostConstruct
    public void init() {
        handlerMap.put("WECHAT", this::handleWechatPay);
        handlerMap.put("ALIPAY", this::handleAlipay);
        handlerMap.put("BANK_CARD", this::handleBankCard);
    }
    
    public PaymentResult pay(PaymentOrder order) {
        PaymentHandler handler = handlerMap.get(order.getPaymentType());
        if (handler == null) {
            throw new IllegalArgumentException("不支持的支付方式");
        }
        return handler.handle(order);
    }
    
    private PaymentResult handleWechatPay(PaymentOrder order) {
        // 微信支付逻辑
    }
    
    private PaymentResult handleAlipay(PaymentOrder order) {
        // 支付宝支付逻辑
    }
    
    private PaymentResult handleBankCard(PaymentOrder order) {
        // 银行卡支付逻辑
    }
}

4.3 对比

方案优点缺点适用场景
if-else简单直接难以扩展、代码臃肿支付方式少且不常变
Map + Function轻量级、易理解逻辑仍在一个类中中等复杂度场景
策略模式 + 枚举完全解耦、易于测试、符合开闭原则类数量增加支付方式多、需要独立测试

五、什么时候不该用策略模式

策略模式虽好,但不是万能的。以下情况不建议使用:

5.1 简单的条件判断

// 如果只有两种情况,if-else 更清晰
if (isVip) {
    price = originalPrice * 0.8;
} else {
    price = originalPrice;
}

5.2 逻辑非常简单

// 逻辑简单到一行就能搞定
return paymentType.equals("WECHAT") ? wechatPay() : alipayPay();

5.3 条件很少变化

// 如果条件几乎不会新增,没必要过度设计
if (type == "A") { ... }
else if (type == "B") { ... }

六、完整示例工程

本文配套提供了完整的示例工程,包含:

  • 策略模式接口和实现类
  • 枚举注册和工厂类
  • 传统 if-else 写法对比
  • 单元测试

6.1 项目结构

strategy-pattern-demo/
├── src/main/java/com/example/demo/
│   ├── PaymentStrategy.java        # 策略接口
│   ├── PaymentType.java            # 支付类型枚举
│   ├── PaymentStrategyFactory.java # 策略工厂
│   ├── strategy/
│   │   ├── WechatPaymentStrategy.java
│   │   ├── AlipayPaymentStrategy.java
│   │   └── BankCardPaymentStrategy.java
│   ├── PaymentService.java         # 支付服务
│   ├── PaymentOrder.java           # 支付订单
│   └── DemoApplication.java        # 启动类
└── pom.xml

6.2 使用方式

# 编译运行
mvn clean compile
mvn spring-boot:run

# 调用示例
curl -X POST http://localhost:8080/api/payment/pay \
  -H "Content-Type: application/json" \
  -d '{
    "orderId": "202401010001",
    "amount": 100.00,
    "paymentType": "WECHAT"
  }'

七、总结

7.1 重构前后对比

维度重构前(if-else)重构后(策略模式 + 枚举)
代码行数100+ 行每个策略 20-30 行
扩展性差(修改原有代码)好(新增类和枚举值)
可测试性差(需要测试整个方法)好(每个策略独立测试)
可读性差(长方法)好(职责清晰)
开闭原则违反符合

7.2 核心优势

  1. 符合开闭原则:对扩展开放,对修改关闭
  2. 职责分离:每个策略负责自己的业务逻辑
  3. 易于测试:每个策略可以独立编写单元测试
  4. 代码清晰:调用方只需一行代码即可完成支付

7.3 最佳实践

  1. 策略类独立:每个策略类放在单独的文件中
  2. 工厂统一管理:通过工厂类获取策略实例
  3. 枚举注册:使用枚举管理策略映射关系
  4. 异常处理:策略内部处理各自的异常

互动话题:你在项目中遇到过哪些 if-else 地狱?是怎么解决的?欢迎留言分享!


附录

设计模式对比

设计模式适用场景本文场景
策略模式多种算法/行为,运行时选择多种支付方式
工厂模式创建对象,隐藏创建逻辑创建策略实例
模板方法模式算法骨架固定,步骤可变支付流程固定,具体实现不同
命令模式请求封装为对象支付请求封装

参考资料


标题:别再写 if-else 了:策略模式 + 枚举让你的代码优雅 10 倍
作者:jiangyi
地址:http://jiangyi.space/articles/2026/07/29/1785082665111.html
公众号:服务端技术精选
    评论
    0 评论
avatar

取消