文章目录
- 背景
- 一、定义银行操作的统一接口(策略接口)
- 二、各银行实现类
- 工商银行
- 农业银行
- 建设银行
- 三、银行类型枚举
- 四、统一的请求和响应对象
- 五、银行操作工厂
- 六、门面类 - 提供统一的接口访问点
- 七、使用示例
- 设计说明
Talk is cheap, show me the code.
背景
项目中要用对接 10 家银行的支付接口、余额查询、流水交易结果查询等接口
作者将尝试使用策略模式 + 门面模式
设计一下API,增加 API 的易用性
一、定义银行操作的统一接口(策略接口)
// 1. 定义银行操作的统一接口(策略接口)
public interface BankOperations {PaymentResult doPayment(PaymentRequest request);BalanceResult queryBalance(BalanceRequest request);TransactionResult queryTransaction(TransactionRequest request);
}
二、各银行实现类
工商银行
// 2. 各银行实现类
public class ICBCBankOperations implements BankOperations {@Overridepublic PaymentResult doPayment(PaymentRequest request) {// 工商银行支付实现return null;}@Overridepublic BalanceResult queryBalance(BalanceRequest request) {// 工商银行余额查询实现return null;}@Overridepublic TransactionResult queryTransaction(TransactionRequest request) {// 工商银行交易查询实现return null;}
}
农业银行
public class ABCBankOperations implements BankOperations {// 农业银行实现...
}
建设银行
public class CCBBankOperations implements BankOperations {// 建设银行实现...
}
三、银行类型枚举
// 3. 银行类型枚举
public enum BankType {ICBC, ABC, CCB
}
四、统一的请求和响应对象
// 4. 统一的请求和响应对象
@Data
public class PaymentRequest {private String accountNo;private BigDecimal amount;private String currency;private String purpose;// 其他通用支付参数...
}@Data
public class PaymentResult {private String transactionId;private String status;private String message;// 其他通用返回字段...
}
五、银行操作工厂
// 5. 银行操作工厂
@Component
public class BankOperationsFactory {private final Map<BankType, BankOperations> operationsMap = new HashMap<>();@Autowiredpublic BankOperationsFactory(List<BankOperations> operations) {// 初始化银行操作实现映射operations.forEach(operation -> {if (operation instanceof ICBCBankOperations) {operationsMap.put(BankType.ICBC, operation);} else if (operation instanceof ABCBankOperations) {operationsMap.put(BankType.ABC, operation);} else if (operation instanceof CCBBankOperations) {operationsMap.put(BankType.CCB, operation);}});}public BankOperations getOperation(BankType bankType) {return operationsMap.get(bankType);}
}
六、门面类 - 提供统一的接口访问点
// 6. 门面类 - 提供统一的接口访问点
@Service
public class BankServiceFacade {private final BankOperationsFactory factory;@Autowiredpublic BankServiceFacade(BankOperationsFactory factory) {this.factory = factory;}public PaymentResult doPayment(BankType bankType, PaymentRequest request) {try {BankOperations operations = factory.getOperation(bankType);return operations.doPayment(request);} catch (Exception e) {log.error("Payment failed", e);return PaymentResult.builder().status("FAILED").message(e.getMessage()).build();}}public BalanceResult queryBalance(BankType bankType, BalanceRequest request) {try {BankOperations operations = factory.getOperation(bankType);return operations.queryBalance(request);} catch (Exception e) {log.error("Balance query failed", e);return BalanceResult.builder().status("FAILED").message(e.getMessage()).build();}}public TransactionResult queryTransaction(BankType bankType, TransactionRequest request) {try {BankOperations operations = factory.getOperation(bankType);return operations.queryTransaction(request);} catch (Exception e) {log.error("Transaction query failed", e);return TransactionResult.builder().status("FAILED").message(e.getMessage()).build();}}
}
七、使用示例
// 7. 使用示例
@Service
public class PaymentService {@Autowiredprivate BankServiceFacade bankService;public void processPayment() {PaymentRequest request = new PaymentRequest();request.setAccountNo("1234567890");request.setAmount(new BigDecimal("100.00"));// 调用工商银行支付PaymentResult result = bankService.doPayment(BankType.ICBC, request);// 处理支付结果...}
}
设计说明
-
策略模式:
- BankOperations 接口定义了所有银行操作的统一接口
- 每个银行都有自己的实现类(ICBCBankOperations, ABCBankOperations, CCBBankOperations)
- 通过工厂类动态选择具体的实现
-
门面模式:
- BankServiceFacade 提供了一个统一的访问点
- 封装了异常处理和日志记录
- 简化了客户端的调用方式
-
扩展性:
- 添加新银行只需要:
- 实现 BankOperations 接口
- 在 BankType 中添加新的枚举值
- 在工厂类中注册新的实现
- 添加新银行只需要:
-
可维护性:
- 每个银行的实现相互独立
- 共用的代码抽取到基类或工具类
- 统一的异常处理和日志记录
-
使用建议:
- 可以添加配置类管理银行的连接参数
- 可以使用适配器模式处理不同银行的返回格式
- 可以添加重试机制和熔断机制
- 建议添加参数验证和安全检查
这样的设计让代码结构清晰,易于维护和扩展,同时也提供了良好的用户体验。