别再写 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 核心优势
- 符合开闭原则:对扩展开放,对修改关闭
- 职责分离:每个策略负责自己的业务逻辑
- 易于测试:每个策略可以独立编写单元测试
- 代码清晰:调用方只需一行代码即可完成支付
7.3 最佳实践
- 策略类独立:每个策略类放在单独的文件中
- 工厂统一管理:通过工厂类获取策略实例
- 枚举注册:使用枚举管理策略映射关系
- 异常处理:策略内部处理各自的异常
互动话题:你在项目中遇到过哪些 if-else 地狱?是怎么解决的?欢迎留言分享!
附录
设计模式对比
| 设计模式 | 适用场景 | 本文场景 |
|---|---|---|
| 策略模式 | 多种算法/行为,运行时选择 | 多种支付方式 |
| 工厂模式 | 创建对象,隐藏创建逻辑 | 创建策略实例 |
| 模板方法模式 | 算法骨架固定,步骤可变 | 支付流程固定,具体实现不同 |
| 命令模式 | 请求封装为对象 | 支付请求封装 |
参考资料
标题:别再写 if-else 了:策略模式 + 枚举让你的代码优雅 10 倍
作者:jiangyi
地址:http://www.jiangyi.space/articles/2026/07/29/1785082665111.html
公众号:服务端技术精选
- 引言
- 一、传统 if-else 写法
- 1.1 支付订单类
- 1.2 支付服务(传统写法)
- 1.3 问题分析
- 二、策略模式 + 枚举重构
- 2.1 定义策略接口
- 2.2 实现具体策略
- 2.3 定义支付类型枚举
- 2.4 创建策略工厂
- 2.5 重构后的支付服务
- 2.6 调用方式
- 三、扩展新支付方式
- 3.1 新增策略实现类
- 3.2 在枚举中注册
- 四、轻量级替代方案:Map + 函数式接口
- 4.1 定义支付处理器
- 4.2 注册处理器
- 4.3 对比
- 五、什么时候不该用策略模式
- 5.1 简单的条件判断
- 5.2 逻辑非常简单
- 5.3 条件很少变化
- 六、完整示例工程
- 6.1 项目结构
- 6.2 使用方式
- 七、总结
- 7.1 重构前后对比
- 7.2 核心优势
- 7.3 最佳实践
- 附录
- 设计模式对比
- 参考资料
评论
0 评论