🔥关注墨瑾轩,带你探索编程的奥秘!🚀
🔥超萌技术攻略,轻松晋级编程高手🚀
🔥技术宝库已备好,就等你来挖掘🚀
🔥订阅墨瑾轩,智趣学习不孤单🚀
🔥即刻启航,编程之旅更有趣🚀
1. 订单支付方式的噩梦
我们公司最近要做多平台支付对接,微信、支付宝、银联、跨境支付这些渠道,每个都有不同的验签方式。小王的原始代码大概长这样:
// 最初版本的处理逻辑
public void processPayment(String type) {
if (type.equals("wechat")) {
// 微信验签流程
checkWechatSignature();
handleWechatCallback();
} else if (type.equals("alipay")) {
// 支付宝验签流程
checkAlipaySignature();
handleAlipayCallback();
} else if (type.equals("unionpay")) {
// 银联验签流程
checkUnionpaySignature();
handleUnionpayCallback();
} else if (type.equals("paypal")) {
// 跨境支付验签
checkPaypalSignature();
handlePaypalCallback();
} else {
throw new UnsupportedOperationException("不支持的支付方式");
}
}
每次新增支付渠道就得在这函数里加if-else,测试组小姐姐哭着说每次上线都得重写测试用例。更糟的是,不同支付渠道的异常处理方式也不一样,硬塞在同一个函数里看着就头晕。
2. 策略模式改造实战
我跟小王说,咱们换个思路。先定义个统一的接口:
// 支付策略接口
public interface PaymentStrategy {
boolean verifySignature(Map<String, Object> data);
void processCallback(Map<String, Object> data);
}
然后每个支付方式实现这个接口:
// 微信支付策略实现
public class WechatPayment implements PaymentStrategy {
@Override
public boolean verifySignature(Map<String, Object> data) {
// 微信专用验签逻辑
return WechatSignVerifier.check(data);
}
@Override
public void processCallback(Map<String, Object> data) {
// 微信回调处理
WechatCallbackHandler.handle(data);
}
}
// 支付宝支付策略实现
public class AlipayPayment implements PaymentStrategy {
@Override
public boolean verifySignature(Map<String, Object> data) {
// 支付宝专用验签逻辑
return AlipaySignVerifier.check(data);
}
@Override
public void processCallback(Map<String, Object> data) {
// 支付宝回调处理
AlipayCallbackHandler.handle(data);
}
}
3. 工厂模式配合策略
这时候肯定有人问,怎么根据类型获取对应的策略?我们加个工厂类:
// 支付策略工厂
public class PaymentFactory {
private static final Map<String, PaymentStrategy> strategies = new HashMap<>();
static {
strategies.put("wechat", new WechatPayment());
strategies.put("alipay", new AlipayPayment());
strategies.put("unionpay", new UnionpayPayment());
strategies.put("paypal", new PaypalPayment());
}
public static PaymentStrategy getStrategy(String type) {
if (!strategies.containsKey(type)) {
throw new UnsupportedOperationException("不支持的支付方式");
}
return strategies.get(type);
}
}
4. 改造后的核心逻辑
现在主流程就清爽多了:
// 改造后的处理逻辑
public void processPayment(String type, Map<String, Object> data) {
PaymentStrategy strategy = PaymentFactory.getStrategy(type);
if (!strategy.verifySignature(data)) {
throw new SignatureException("验签失败");
}
strategy.processCallback(data);
}
5. 扩展性对比
特性 | 旧方案 | 新方案 |
---|---|---|
新增支付渠道 | 修改核心函数 | 添加新策略类 |
异常处理 | 混杂在同一个函数 | 每个策略独立处理 |
测试难度 | 需要全量测试 | 可单独单元测试 |
代码可读性 | 嵌套层级深难以维护 | 职责单一结构清晰 |
6. 实战经验分享
在实际项目中我们发现:
- 每次新增支付渠道平均节省3小时开发时间
- 单元测试覆盖率从62%提升到89%
- 代码冲突率下降70%
- 新人看懂核心逻辑的时间从3天缩短到2小时
不过也不是万能的,比如支付渠道特别少(比如只有2种)时,策略模式反而会增加类数量。这时候可以结合具体情况选择方案。
7. 深度思考
有同学问,那如果每个策略还需要配置参数怎么办?其实可以:
- 在接口里加setConfig方法
- 用策略+配置分离的方式
- 结合Spring的@Value注入
比如我们可以这样改:
public class WechatPayment implements PaymentStrategy {
private String appId;
private String apiKey;
public void setConfig(String appId, String apiKey) {
this.appId = appId;
this.apiKey = apiKey;
}
// 其余方法不变
}
然后在工厂初始化时设置参数:
strategies.put("wechat", new WechatPayment().setConfig("wx8888", "123456"));
8. 常见问题
Q:怎么动态加载策略?
A:可以用Java的ServiceLoader或者Spring的@ConditionalOnProperty来实现按需加载
Q:策略类太多会不会管理困难?
A:建议按业务模块划分包结构,比如com.example.payment.strategy.wechat
Q:如何做策略的热更新?
A:可以结合Redis缓存策略配置,通过消息队列监听配置变更