枚举策略模式实战:优雅消除支付场景的if-else
在支付场景中使用枚举实现策略模式,可以优雅地消除if-else
语句,提高代码的可读性、可维护性和扩展性。以下是具体实现方案:
1. 定义策略枚举
@Getter
@RequiredArgsConstructor
public enum PaymentStrategy {ALIPAY(1, "支付宝") {@Overridepublic void processPayment(BigDecimal amount) {System.out.println("支付宝支付: " + amount + "元");// 调用支付宝SDK的具体逻辑}},WECHAT_PAY(2, "微信支付") {@Overridepublic void processPayment(BigDecimal amount) {System.out.println("微信支付: " + amount + "元");// 调用微信支付SDK的具体逻辑}},CREDIT_CARD(3, "信用卡支付") {@Overridepublic void processPayment(BigDecimal amount) {System.out.println("信用卡支付: " + amount + "元");// 调用银行API的逻辑}};/*** 编码*/private final Integer code;/*** 说明*/private final String desc;/*** 抽象支付方法(策略接口)* @param amount 支付金额*/public abstract void processPayment(BigDecimal amount);
}
2. 上下文处理器(消除 if-else)
public class PaymentProcessor {public void executePayment(String paymentType, BigDecimal amount) {// 通过枚举名直接获取策略(无需条件判断)PaymentStrategy strategy = PaymentStrategy.valueOf(paymentType.toUpperCase());strategy.processPayment(amount);}
}
3. 客户端调用
public class Client {public static void main(String[] args) {PaymentProcessor processor = new PaymentProcessor();// 直接通过支付类型字符串调用(无if-else)processor.executePayment("ALIPAY", new BigDecimal("100.50"));processor.executePayment("WECHAT_PAY", new BigDecimal("200.00"));}
}
优势分析
消除条件判断:
直接通过
valueOf()
将字符串映射到枚举策略,彻底消除if-else/switch
开闭原则:
// 扩展新支付方式只需添加枚举常量 PaymentStrategy.BANK_TRANSFER {@Overridepublic void processPayment(BigDecimal amount) {System.out.println("银行转账: " + amount);} };
新增策略时 无需修改已有代码,符合开放-封闭原则
强类型约束:
编译器会强制要求每个枚举实现策略方法
避免字符串拼写错误(
IllegalArgumentException
)
策略集中管理:
所有策略在枚举中一目了然
天然的单例保证(无需考虑线程安全问题)
处理非法支付类型
public void executePayment(String paymentType, BigDecimal amount) {try {PaymentStrategy strategy = PaymentStrategy.valueOf(paymentType.toUpperCase());strategy.processPayment(amount);} catch (IllegalArgumentException e) {// 统一处理未知支付类型throw new UnsupportedPaymentTypeException("不支持的支付方式: " + paymentType);}
}
适用场景
策略类型固定且有限(如支付方式、状态机)
需要强类型约束和编译期检查
策略本身无需复杂状态维护
对比传统工厂模式:枚举策略模式更简洁,但扩展性略低于类层次结构实现。适合策略数量可控的场景,若策略行为过于复杂或需要动态加载,建议采用传统接口+实现类的方式。