策略模式和适配器模式的混合使用

Lior

策略模式和适配器模式的混合使用

整体架构图

1
你的业务代码 → 统一支付接口 → 策略工厂 → 具体策略 → 适配器 → 第三方SDK

代码逐行解释

1. 统一支付接口(策略模式的核心)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 统一支付接口 - 这是策略模式中的"策略接口"
* 作用:定义所有支付方式都必须遵守的统一标准
* 就像制定一个"USB接口标准",不管是苹果还是安卓都要按这个标准来做
*/
public interface PaymentProcessor {
/**
* 统一支付方法
* @param orderId 订单号
* @param amount 金额
* @param subject 商品标题
* @param notifyUrl 回调地址
*/
PaymentResult pay(String orderId, BigDecimal amount, String subject, String notifyUrl);
}

2. 第三方SDK(被适配的老系统)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
* 支付宝SDK - 这是"被适配者"(Adaptee)
* 作用:真实的第三方支付SDK,但它的接口和我们想要的接口不一样
* 就像一台美式咖啡机,只能用110V电压,插头是两脚扁的
*/
public class AlipaySDK {
/**
* 支付宝的支付方法 - 接口设计很奇怪
* 参数顺序、命名、格式都和我们想要的不一样
* @param bizContent 业务参数(JSON字符串,包含订单信息)
* @param returnUrl 返回地址(我们其实不需要)
* @param notifyUrl 回调地址(我们需要的)
*/
public String tradeAppPay(String bizContent, String returnUrl, String notifyUrl) {
// 这里是支付宝自己的实现逻辑
// 1. 解析bizContent中的订单信息
// 2. 调用支付宝服务器API
// 3. 生成支付参数串
System.out.println("调用支付宝SDK,参数:" + bizContent);
return "alipay_sdk_result_string"; // 返回支付宝格式的支付串
}
}

/**
* 微信支付SDK - 另一个被适配者
* 作用:同样是第三方SDK,接口也不一样
* 就像一台意式咖啡机,只能用220V电压,插头是三脚的
*/
public class WechatPaySDK {
/**
* 微信的统一下单方法 - 又是另一种接口设计
* @param body 商品描述(相当于我们的subject)
* @param totalFee 总金额(单位是分!不是元)
* @param outTradeNo 商户订单号(相当于我们的orderId)
* @param notifyUrl 回调地址
* @param tradeType 交易类型(APP、JSAPI等)
*/
public Map<String, String> unifiedOrder(String body, int totalFee, String outTradeNo,
String notifyUrl, String tradeType) {
// 微信自己的实现逻辑
// 1. 组装微信要求的参数格式
// 2. 调用微信支付API
// 3. 返回预支付ID等信息
System.out.println("调用微信SDK,订单号:" + outTradeNo);
Map<String, String> result = new HashMap<>();
result.put("prepay_id", "wx_" + outTradeNo + "_12345");
return result;
}
}

3. 适配器(解决接口不匹配)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/**
* 支付宝适配器 - 这是适配器模式的核心
* 作用:把支付宝的接口"翻译"成我们统一的接口
* 就像一个电源转换器,把220V转换成110V,两脚扁插头转换成三脚圆插头
*/
@Component("alipayAdapter") // Spring注解:把这个类注册为Spring管理的Bean,名字叫"alipayAdapter"
public class AlipayAdapter implements PaymentProcessor { // 实现统一接口

// 持有支付宝SDK的引用 - 这就是"组合"关系
private AlipaySDK alipaySDK;

// 构造方法 - 传入支付宝SDK实例
public AlipayAdapter(AlipaySDK alipaySDK) {
this.alipaySDK = alipaySDK;
}

/**
* 实现统一支付接口 - 这里是"适配"发生的地方
* 把我们的标准参数转换成支付宝需要的参数格式
*/
@Override
public PaymentResult pay(String orderId, BigDecimal amount, String subject, String notifyUrl) {
try {
// 第一步:参数转换 - 把我们的参数打包成支付宝需要的JSON格式
String bizContent = buildBizContent(orderId, amount, subject);
System.out.println("转换参数:orderId=" + orderId + " → bizContent=" + bizContent);

// 第二步:调用支付宝SDK - 使用转换后的参数
String alipayResult = alipaySDK.tradeAppPay(bizContent, null, notifyUrl);

// 第三步:结果转换 - 把支付宝的结果转换成我们统一的结果格式
PaymentResult result = PaymentResult.success("ALIPAY", alipayResult);
System.out.println("支付宝支付成功:" + result);

return result;

} catch (Exception e) {
// 异常处理
System.err.println("支付宝支付失败:" + e.getMessage());
return PaymentResult.failure("ALIPAY_ERROR", e.getMessage());
}
}

/**
* 私有方法:构建支付宝需要的业务参数
* 这就是"适配"的具体实现
*/
private String buildBizContent(String orderId, BigDecimal amount, String subject) {
// 创建一个JSON对象,按照支付宝的要求组织参数
JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", orderId); // 商户订单号
bizContent.put("total_amount", amount.setScale(2, RoundingMode.HALF_UP).toString()); // 金额,保留2位小数
bizContent.put("subject", subject); // 商品标题
bizContent.put("product_code", "QUICK_MSECURITY_PAY"); // 产品码,固定值

System.out.println("构建支付宝参数:" + bizContent.toJSONString());
return bizContent.toJSONString();
}
}

/**
* 微信支付适配器 - 另一个适配器
* 作用和支付宝适配器一样,但是适配微信的接口
*/
@Component("wechatPayAdapter")
public class WechatPayAdapter implements PaymentProcessor {

private WechatPaySDK wechatPaySDK;

public WechatPayAdapter(WechatPaySDK wechatPaySDK) {
this.wechatPaySDK = wechatPaySDK;
}

@Override
public PaymentResult pay(String orderId, BigDecimal amount, String subject, String notifyUrl) {
try {
// 微信的金额单位是分,需要转换
int totalFeeInCent = amount.multiply(new BigDecimal(100)).intValue();
System.out.println("金额转换:" + amount + "元 → " + totalFeeInCent + "分");

// 调用微信SDK
Map<String, String> wechatResult = wechatPaySDK.unifiedOrder(
subject, // body
totalFeeInCent, // total_fee (单位:分)
orderId, // out_trade_no
notifyUrl, // notify_url
"APP" // trade_type
);

// 转换结果
PaymentResult result = PaymentResult.success("WECHAT_PAY", wechatResult.get("prepay_id"));
System.out.println("微信支付成功:" + result);

return result;

} catch (Exception e) {
System.err.println("微信支付失败:" + e.getMessage());
return PaymentResult.failure("WECHAT_ERROR", e.getMessage());
}
}
}

4. 策略工厂(根据类型选择适配器)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* 支付策略工厂 - 策略模式的核心
* 作用:根据支付类型返回对应的支付处理器
* 就像一个餐厅的点餐系统,你说要"川菜",它就给你川菜厨师;你说要"粤菜",它就给你粤菜厨师
*/
@Service // Spring注解:标记为业务层的服务类
public class PaymentStrategyFactory {

// Spring会自动把所有PaymentProcessor类型的Bean注入到这个Map中
// Key是Bean的名字,Value是对应的Bean实例
@Autowired
private Map<String, PaymentProcessor> processorMap;

/**
* 根据支付类型获取对应的处理器
* @param paymentType 支付类型:ALIPAY、WECHAT等
* @return 对应的支付处理器
*/
public PaymentProcessor getProcessor(String paymentType) {
// 根据支付类型拼接Bean名称
// 比如:ALIPAY → alipayAdapter,WECHAT → wechatPayAdapter
String beanName = paymentType.toLowerCase() + "Adapter";

System.out.println("查找支付处理器:" + paymentType + " → " + beanName);

// 从Map中获取对应的处理器
PaymentProcessor processor = processorMap.get(beanName);

if (processor == null) {
// 如果没有找到对应的处理器,抛出异常
throw new IllegalArgumentException("不支持的支付方式: " + paymentType + ",可用类型:" + processorMap.keySet());
}

System.out.println("找到处理器:" + processor.getClass().getSimpleName());
return processor;
}

/**
* 获取所有可用的支付方式
* @return 支付方式列表
*/
public List<String> getAvailablePaymentTypes() {
return processorMap.keySet().stream()
.map(name -> name.replace("Adapter", "").toUpperCase())
.collect(Collectors.toList());
}
}

5. 业务服务层(使用工厂)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/**
* 支付业务服务 - 这是真正执行业务逻辑的地方
* 作用:协调各个组件完成支付流程
* 就像餐厅的前台服务员,负责接待客户、安排座位、通知厨房
*/
@Service
@Transactional // 事务注解:确保支付操作的原子性
public class PaymentService {

// 注入支付策略工厂
@Autowired
private PaymentStrategyFactory factory;

// 注入订单服务(假设存在)
@Autowired
private OrderService orderService;

/**
* 处理支付请求
* @param request 支付请求
* @return 支付结果
*/
public PaymentResult processPayment(PaymentRequest request) {
System.out.println("=== 开始处理支付 ===");
System.out.println("订单号:" + request.getOrderId());
System.out.println("支付方式:" + request.getPaymentType());
System.out.println("支付金额:" + request.getAmount());

try {
// 第一步:参数验证
validatePaymentRequest(request);

// 第二步:获取对应的支付处理器 - 策略模式的核心
PaymentProcessor processor = factory.getProcessor(request.getPaymentType());
System.out.println("使用处理器:" + processor.getClass().getSimpleName());

// 第三步:执行支付 - 多态调用!
// 这里的processor可能是AlipayAdapter,也可能是WechatPayAdapter
// 但调用的都是相同的pay方法,这就是多态的威力
PaymentResult result = processor.pay(
request.getOrderId(),
request.getAmount(),
request.getSubject(),
request.getNotifyUrl()
);

// 第四步:处理支付结果
if (result.isSuccess()) {
// 支付成功,更新订单状态
orderService.updateOrderStatus(request.getOrderId(), OrderStatus.PAID);
System.out.println("✅ 支付成功!");
} else {
// 支付失败,记录日志
System.err.println("❌ 支付失败:" + result.getMessage());
}

return result;

} catch (Exception e) {
System.err.println("💥 支付过程异常:" + e.getMessage());
return PaymentResult.failure("SYSTEM_ERROR", "系统异常,请稍后重试");
}
}

/**
* 验证支付请求
*/
private void validatePaymentRequest(PaymentRequest request) {
if (request == null) {
throw new IllegalArgumentException("支付请求不能为空");
}
if (StringUtils.isBlank(request.getOrderId())) {
throw new IllegalArgumentException("订单号不能为空");
}
if (request.getAmount().compareTo(Bigecimal.ZERO) <= 0) {
throw new IllegalArgumentException("支付金额必须大于0");
}
if (StringUtils.isBlank(request.getPaymentType())) {
throw new IllegalArgumentException("支付方式不能为空");
}
}
}

6. 控制器层(接收HTTP请求)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
* 支付控制器 - 接收前端HTTP请求
* 作用:处理REST API调用,调用业务服务
* 就像餐厅的门迎,负责接待客人,把客人的需求传递给内部
*/
@RestController // Spring注解:标记为REST控制器
@RequestMapping("/api/payment") // 设置API路径前缀
public class PaymentController {

@Autowired
private PaymentService paymentService;

/**
* 统一支付接口
* POST /api/payment/pay
*/
@PostMapping("/pay")
public ResponseEntity<ApiResponse> pay(@RequestBody @Valid PaymentRequest request) {
System.out.println("📱 收到支付请求:" + request);

try {
// 调用支付服务
PaymentResult result = paymentService.processPayment(request);

if (result.isSuccess()) {
// 返回成功响应
return ResponseEntity.ok(ApiResponse.success(result));
} else {
// 返回失败响应
return ResponseEntity.badRequest().body(ApiResponse.error(result.getMessage()));
}

} catch (Exception e) {
System.err.println("💥 控制器异常:" + e.getMessage());
return ResponseEntity.internalServerError()
.body(ApiResponse.error("系统繁忙,请稍后重试"));
}
}

/**
* 查询支持的支付方式
* GET /api/payment/types
*/
@GetMapping("/types")
public ResponseEntity<ApiResponse> getPaymentTypes() {
try {
List<String> types = paymentService.getAvailablePaymentTypes();
return ResponseEntity.ok(ApiResponse.success(types));
} catch (Exception e) {
return ResponseEntity.internalServerError()
.body(ApiResponse.error("获取支付方式失败"));
}
}
}

7. 数据传输对象(DTO)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
* 支付请求DTO - 前端传给后端的参数
* 作用:封装前端传递的支付参数
*/
public class PaymentRequest {
@NotBlank(message = "订单号不能为空")
private String orderId;

@NotNull(message = "支付金额不能为空")
@DecimalMin(value = "0.01", message = "支付金额必须大于0")
private BigDecimal amount;

@NotBlank(message = "商品标题不能为空")
private String subject;

@NotBlank(message = "支付方式不能为空")
private String paymentType; // ALIPAY, WECHAT

@NotBlank(message = "回调地址不能为空")
private String notifyUrl;

// getter和setter方法
public String getOrderId() { return orderId; }
public void setOrderId(String orderId) { this.orderId = orderId; }

public BigDecimal getAmount() { return amount; }
public void setAmount(BigDecimal amount) { this.amount = amount; }

public String getSubject() { return subject; }
public void setSubject(String subject) { this.subject = subject; }

public String getPaymentType() { return paymentType; }
public void setPaymentType(String paymentType) { this.paymentType = paymentType; }

public String getNotifyUrl() { return notifyUrl; }
public void setNotifyUrl(String notifyUrl) { this.notifyUrl = notifyUrl; }

@Override
public String toString() {
return "PaymentRequest{" +
"orderId='" + orderId + '\'' +
", amount=" + amount +
", subject='" + subject + '\'' +
", paymentType='" + paymentType + '\'' +
", notifyUrl='" + notifyUrl + '\'' +
'}';
}
}

/**
* 支付结果DTO - 后端返回给前端的结果
* 作用:统一支付结果的格式
*/
public class PaymentResult {
private boolean success; // 是否成功
private String code; // 错误码
private String message; // 错误信息
private String paymentType; // 支付方式
private Object data; // 支付数据(如支付宝支付串、微信预支付ID等)

// 成功静态方法
public static PaymentResult success(String paymentType, Object data) {
PaymentResult result = new PaymentResult();
result.success = true;
result.paymentType = paymentType;
result.data = data;
return result;
}

// 失败静态方法
public static PaymentResult failure(String code, String message) {
PaymentResult result = new PaymentResult();
result.success = false;
result.code = code;
result.message = message;
return result;
}

// getter方法
public boolean isSuccess() { return success; }
public String getCode() { return code; }
public String getMessage() { return message; }
public String getPaymentType() { return paymentType; }
public Object getData() { return data; }
}

/**
* API响应DTO - 统一的API响应格式
*/
public class ApiResponse {
private boolean success;
private String message;
private Object data;

public static ApiResponse success(Object data) {
ApiResponse response = new ApiResponse();
response.success = true;
response.data = data;
return response;
}

public static ApiResponse error(String message) {
ApiResponse response = new ApiResponse();
response.success = false;
response.message = message;
return response;
}

// getter方法省略
}

完整调用流程示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 前端发送的HTTP请求:
POST /api/payment/pay
{
"orderId": "ORDER_123456",
"amount": 99.99,
"subject": "iPhone手机壳",
"paymentType": "ALIPAY",
"notifyUrl": "https://your-domain.com/notify/alipay"
}

// 后端处理流程:
1. PaymentController.pay() 接收到请求
2. 调用 PaymentService.processPayment(request)
3. PaymentService 调用 PaymentStrategyFactory.getProcessor("ALIPAY")
4. Factory 返回 AlipayAdapter 实例
5. PaymentService 调用 processor.pay(...),实际执行 AlipayAdapter.pay(...)
6. AlipayAdapter 将参数转换为支付宝格式,调用 AlipaySDK.tradeAppPay(...)
7. 支付宝SDK返回结果,AlipayAdapter 转换为统一格式返回
8. PaymentService 处理业务逻辑,更新订单状态
9. 返回结果给前端

核心思想总结

-

适配器模式:让不同的支付SDK看起来都一样

-

策略模式:根据支付类型选择不同的处理方式

-

多态:同样的接口调用,执行不同的具体实现

-

工厂模式:负责创建和管理这些处理器

  • Title: 策略模式和适配器模式的混合使用
  • Author: Lior
  • Created at : 2026-01-07 11:10:00
  • Updated at : 2026-01-07 13:06:06
  • Link: https://newblog.buleng.xyz/2/
  • License: This work is licensed under CC BY-NC-SA 4.0.