一、背景
在现代支付系统中,往往需要对接多家支付公司(如支付宝、微信、银联等)以及其下的多种支付产品(如扫码支付、刷脸支付、退款等)。如果每种支付方式都单独开发,会导致代码冗余、维护困难。为此,采用模板方法模式 +工厂模式的组合,是一种高内聚、低耦合的优雅实现方式。
二、现有设计回顾
1. 模板方法接口
java
public interface UnitPayTemplate<T> extends InitializingBean {
default Map pay(T t) { ... }
default Map refund(T t) { ... }
default Map query(T t) { ... }
default Map cancel(T t) { ... }
Map<String, Object> packageParam(T t);
Map sendRequest(Map<String, Object> params);
}
- 通过泛型
T
支持不同的参数类型。 - 默认实现了常用的支付操作,具体参数组装和请求发送由子类实现。
2. 工厂类
java
public class UnitIndependPayFactory {
private static final Map<String, UnitPayTemplate<?>> services = new ConcurrentHashMap<>();
public static <T> void setInstance(String serviceName, UnitPayTemplate<T> unitPayTemplate) { ... }
public static <T> UnitPayTemplate<T> getInstance(String serviceName) { ... }
}
- 通过
serviceName
注册和获取不同的支付实现。 - 支持线程安全和泛型。
3. 自动注册
每个支付实现类在 afterPropertiesSet()
中自动注册到工厂:
java
@Override
public void afterPropertiesSet() {
UnitIndependPayFactory.setInstance("ALIPAY_ORDER_PAY", this);
}
三、优化建议:支持多支付公司和多产品
1. 设计目标
- 扩展性:支持任意支付公司和产品的组合
- 解耦:业务代码无需关心具体实现
- 灵活注册:可动态扩展新的支付公司/产品
2. 优化方案
2.1 统一Key设计
将 serviceName
设计为 支付公司_产品类型
组合,例如:ALIPAY_ORDER_PAY
、WECHAT_REFUND
。
2.2 支持多公司多产品的模板实现
每个支付公司/产品实现一个模板类,实现 UnitPayTemplate<T>
,如:
java
@Service
public class AliPayOrderPayTemplate implements UnitPayTemplate<AliPayOrderDTO> {
@Override
public Map<String, Object> packageParam(AliPayOrderDTO dto) { ... }
@Override
public Map sendRequest(Map<String, Object> params) { ... }
@Override
public void afterPropertiesSet() {
UnitIndependPayFactory.setInstance("ALIPAY_ORDER_PAY", this);
}
}
2.3 工厂获取实例
业务层只需通过工厂获取对应实例:
java
UnitPayTemplate<?> payTemplate = UnitIndependPayFactory.getInstance("ALIPAY_ORDER_PAY");
payTemplate.pay(dto);
2.4 支持配置化注册
可将支付公司和产品类型配置在数据库或配置文件中,动态注册和加载。
3. 示例代码
3.1 枚举定义
java
public enum PayCompany {
ALIPAY, WECHAT, UNIONPAY
}
public enum PayProduct {
ORDER_PAY, REFUND, QUERY, CANCEL
}
3.2 工厂Key生成工具
java
public class PayKeyUtil {
public static String buildKey(PayCompany company, PayProduct product) {
return company.name() + "_" + product.name();
}
}
3.3 业务调用
java
String key = PayKeyUtil.buildKey(PayCompany.ALIPAY, PayProduct.ORDER_PAY);
UnitPayTemplate<AliPayOrderDTO> payTemplate = UnitIndependPayFactory.getInstance(key);
payTemplate.pay(dto);
四、总结
通过模板方法+工厂模式的组合,可以优雅地支持多支付公司、多产品的扩展需求。只需实现对应的模板类并注册到工厂,业务层即可通过统一接口调用,极大提升了系统的可维护性和扩展性。