多态需配合接口、工厂等结构才能解耦;支付模块应定义PaymentHandler接口,各渠道独立实现,业务层只依赖接口;工厂按渠道标识创建实例,运行时绑定,新增渠道无需修改调用方代码。

多态本身不是设计模式,而是一种语言机制;它真正发挥解耦作用,必须配合接口、工厂或策略等结构来组织代码。关键不在于“用了多态”,而在于是否让业务逻辑彻底摆脱对具体实现的感知。
用接口定义“能做什么”,而不是“是谁在做”
比如支付模块,不要写 if (type.equals("alipay")) { new AlipayProcessor().execute() },而是定义统一接口:
-
声明行为契约:定义
PaymentHandler接口,只含execute(Order order)方法 - 各渠道独立实现:微信、支付宝、银联各自实现该接口,互不影响
-
业务层只依赖接口:订单服务持有
PaymentHandler引用,调用时完全不知背后是哪个类
把“谁来干”交给抽象工厂,避免硬编码创建逻辑
不能靠 if-else 或静态工厂判断类型再 new,否则新增渠道就得改工厂代码。正确做法是:
- 定义
PaymentHandlerFactory接口,声明create(String channel)方法 - 每个渠道对应一个工厂实现,如
AlipayHandlerFactory - 通过 Spring 的
@Qualifier或配置自动注入对应工厂,业务类构造器接收工厂即可 - 运行时根据渠道标识(如
"alipay")获取 handler,全程不出现类名字符串
运行时绑定,编译期零感知
业务代码调用 handler.execute(order) 时,JVM 在运行时才决定执行哪个子类的实现。这意味着:
立即学习“Java免费学习笔记(深入)”;
- 新增一种支付方式?只需加一个实现类 + 一个工厂类 + 配置注册
- 订单服务、风控服务、对账服务等所有调用方,一行代码都不用动
- 禁止在业务层使用
instanceof或强制转型——这是解耦失败的明确信号
配合配置驱动,切断语义与实现的硬绑定
传参别用类全限定名(如 "com.xxx.AlipayHandler"),而用业务语义标识(如 "alipay"):
- 工厂内部做映射,即使重构包路径或重命名类,上层完全无感
- 配置可来自
application.yml、数据库甚至远程配置中心 - 支持运行时热更新渠道开关,无需重启服务


















