多态是解耦与扩展的基础设施,而非语法糖;在支付网关中体现为接口契约+服务发现+动态路由,在规则引擎中体现为规则对象化与执行即多态,需通过元数据外置、无状态接口和工厂注入真落地。

多态不是语法糖,而是解耦与扩展的基础设施。在现代微服务支付网关和轻量规则引擎中,它不靠抽象堆砌,而靠接口契约+运行时注入+策略路由真正落地。
支付网关中的多态:统一入口,动态分发
微服务架构下,支付渠道(微信、支付宝、PayPal、银联等)必须独立部署、独立运维。多态在此处解决的核心问题是:如何让网关层不感知具体实现,又能精准路由并调用对应逻辑。
- 定义 PaymentGateway 接口(或 Spring 中的
PaymentService),声明pay()、refund()、query()等标准方法 - 每个渠道作为独立微服务(如
wechat-pay-svc、alipay-svc),实现该接口,并注册为可发现服务(通过 Nacos/Eureka) - 网关层不做 if-else 判断,而是通过「渠道编码 + 服务发现」查出目标实例,再通过 Feign/RPC 调用其接口——实际调用的是子类实现,但网关代码只面向接口编程
- 新增渠道只需上线新服务 + 配置路由映射(如
channel=unionpay → service-id=unionpay-svc),网关零代码变更
规则引擎中的多态:规则即对象,执行即多态
当规则引擎不依赖 Drools 这类重型框架,而是基于 Java 多态自研轻量方案时,多态体现为“规则对象化”:每条规则是一个实现了 Rule 接口的实例,不同业务场景(风控、营销、审批)各自提供子类实现。
- 定义 Rule 接口:
boolean matches(Context ctx)+void execute(Context ctx) - 风控规则写成
FraudAmountRule、DeviceBlacklistRule;营销规则写成FirstOrderDiscountRule、RegionalCouponRule - 规则引擎核心仅维护
List<Rule>,遍历执行matches()判断是否触发,再调用execute()——无需 switch 或反射,JVM 自动绑定到各子类的具体逻辑 - 规则热加载时,直接 new 实例并 add 进列表;下线时 remove 即可。整个过程对执行引擎透明
关键落地细节:避免“伪多态”陷阱
很多项目号称用了多态,实则仍是条件分支驱动,本质是“披着多态外衣的硬编码”。真落地需守住三条线:
- 接口无状态:PaymentService / Rule 接口不能暴露渠道名、规则ID等判断字段,否则调用方又得写 if 匹配
-
注入不由代码控制:Spring 中禁用
@Qualifier("wechat")手动指定 Bean;改用工厂类根据 channel 动态获取PaymentService实例(如paymentFactory.getService("wechat")) - 规则/渠道元数据外置:渠道配置、规则优先级、启用开关等必须存于配置中心(Apollo/Nacos)或数据库,而非硬编码在类名或注解里
为什么微服务 + 多态比单体 + 多态更自然?
单体应用里,所有实现类都在一个 JVM,多态容易沦为“编译期约定”;而在微服务中,多态被迫延伸为“跨进程契约”——接口定义即 API 规范,实现即服务合约。这种强制分离反而倒逼设计清晰:
- 支付接口必须定义明确入参结构(如
PayRequestDTO),不能靠运行时 instanceof 判断类型 - 规则执行上下文
Context必须包含通用字段(userId、orderId、timestamp),子类不得擅自扩展私有字段 - 错误码、重试策略、幂等键等非功能需求,也需在接口层面统一约定,由各子服务自行实现保障

















