一、模式定义与价值
适配器模式(Adapter Pattern)是一种结构型设计模式,其核心价值在于解决接口不兼容问题。如同现实中的电源转换器,它能在不修改已有代码的基础上,让原本不兼容的接口协同工作。该模式符合开闭原则,有效提高系统扩展性。
二、典型业务场景
某电商系统需要接入多个支付渠道(支付宝、微信、银联),各渠道接口差异显著:
- 支付宝:
AliPayClient#aliPay(String orderNo, BigDecimal amount) - 微信:
WechatPayClient#wechatPay(String userId, BigDecimal amount) - 银联:
UnionPayClient#processPayment(Map<String, Object> params)
系统需要统一支付入口,降低业务层与具体支付实现的耦合度。
三、模式实现详解
1. 统一支付接口定义
public interface PayService {
/**
* 统一支付接口
* @param request 支付请求封装
* @return 支付平台交易号
*/
String pay(PayRequest request);
}
// 支付请求参数封装
@Data
public class PayRequest {
private String orderNo;
private BigDecimal amount;
private String userId;
// 其他扩展字段...
}
2. 支付宝适配器实现
public class AlipayAdapter implements PayService {
private final AliPayClient aliPayClient;
public AlipayAdapter(AliPayClient aliPayClient) {
this.aliPayClient = aliPayClient;
}
@Override
public String pay(PayRequest request) {
// 参数适配转换
String orderNo = request.getOrderNo();
BigDecimal amount = request.getAmount();
// 调用原生接口
return aliPayClient.aliPay(orderNo, amount);
}
}
3. 微信支付适配器实现
public class WechatAdapter implements PayService {
private final WechatPayClient wechatClient;
public WechatAdapter(WechatPayClient wechatClient) {
this.wechatClient = wechatClient;
}
@Override
public String pay(PayRequest request) {
// 参数适配
String userId = request.getUserId();
BigDecimal amount = request.getAmount();
// 调用原生接口
return wechatClient.wechatPay(userId, amount);
}
}
4. 银联支付适配器(展示复杂参数处理)
public class UnionPayAdapter implements PayService {
private final UnionPayClient unionPayClient;
public UnionPayAdapter(UnionPayClient unionPayClient) {
this.unionPayClient = unionPayClient;
}
@Override
public String pay(PayRequest request) {
// 构建银联专用参数
Map<String, Object> params = new HashMap<>();
params.put("merchantOrderNo", request.getOrderNo());
params.put("txnAmt", request.amount.multiply(BigDecimal.valueOf(100)).longValue());
params.put("userId", request.getUserId());
// 调用原生接口
return unionPayClient.processPayment(params);
}
}
四、客户端调用示例
public class PaymentController {
private Map<PayChannel, PayService> payServices = new EnumMap<>(PayChannel.class);
@PostConstruct
public void init() {
payServices.put(PayChannel.ALIPAY, new AlipayAdapter(new AliPayClient()));
payServices.put(PayChannel.WECHAT, new WechatAdapter(new WechatPayClient()));
payServices.put(PayChannel.UNIONPAY, new UnionPayAdapter(new UnionPayClient()));
}
public String handlePayment(PayChannel channel, PayRequest request) {
PayService payService = payServices.get(channel);
return payService.pay(request);
}
}
五、模式优势分析
- 解耦价值:业务层与具体支付实现完全解耦
- 可维护性:新增支付渠道只需添加适配器,无需修改现有代码
- 统一入口:标准化支付接口,降低调用复杂度
- 异常处理:可在适配器中统一处理各渠道的异常码转换
六、适用场景扩展
- 日志框架适配:SLF4J 作为门面模式,底层对接 Log4j/Logback
- 数据格式转换:XML 与 JSON 格式互转适配
- 设备驱动开发:统一操作接口适配不同硬件设备
- 第三方SDK封装:不同云服务商的OSS操作适配
七、架构思考
- 对象适配器 vs 类适配器:Java推荐使用对象组合方式(如本文示例),避免多重继承带来的复杂度
- 与外观模式区别:适配器侧重接口转换,外观模式侧重接口简化
- 性能考量:在高频调用场景需注意适配器带来的间接调用开销
通过适配器模式,我们成功将差异化的支付接口转换为统一的服务接口。这种设计使得支付渠道的增减不再影响核心业务流程,有效提高了系统的可维护性和扩展性。开发者在实际应用中可根据业务复杂度,灵活选择适配粒度和实现方式。
32

被折叠的 条评论
为什么被折叠?



