多态通过统一接口或父类实现扩展性,新增子类无需修改调用逻辑;应避免if-else硬编码,依赖工厂或Spring管理实例,接口设计需抽象适度,特殊行为优先用策略模式而非强制转型。

多态让新增子类无需修改已有调用逻辑
当业务需要扩展新功能(比如新增一种支付方式 ApplePay),只要让新类继承统一父类或实现同一接口(如 Payment),所有使用 Payment 类型的地方——包括订单服务、日志统计、风控校验等模块——都不用改代码。JVM 在运行时自动绑定到具体子类的 pay() 方法。
常见错误是把调用写死:
if (type.equals("alipay")) {
new Alipay().pay();
} else if (type.equals("wechat")) {
new WechatPay().pay();
}这种写法每次加新支付方式都要动 if-else,违反开闭原则。
接口定义稳定,实现可独立演进
系统上线后,老支付渠道可能升级协议(如微信支付从 v2 升级到 v3),只需重写 WechatPayV3 类的 pay() 和 refund() 方法,而 OrderService 中的 payment.pay(order) 这行代码完全不用碰。
关键点在于:
-
Payment接口的方法签名必须足够抽象(比如不暴露 HTTP 细节) - 各子类内部可自由引入新依赖(
WechatPayV3用OkHttpClient,Alipay用HttpClient),不影响上层 - 如果某子类需额外配置(如密钥路径),应通过构造函数或
setXxx()注入,而非在接口里加方法
配合工厂或 Spring Bean 管理,避免 new 出现散落各处
直接 new Alipay() 会把对象创建逻辑耦合进业务代码,导致后续无法统一拦截、打点或替换实现。推荐做法是集中管理:
立即学习“Java免费学习笔记(深入)”;
@Service
public class PaymentFactory {
private final Map paymentMap;
public PaymentFactory(List payments) {
this.paymentMap = payments.stream()
.collect(Collectors.toMap(Payment::getType, p -> p));
}
public Payment get(String type) {
return paymentMap.get(type);
}
}
这样新增支付方式,只用加一个 @Component 类并实现 getType(),Spring 自动注入进 paymentMap,无其他代码改动。
注意运行时类型检查和强制转型的陷阱
多态不等于放弃类型安全。如果业务逻辑确实需要针对某子类做特殊处理(比如只有 Alipay 支持红包抵扣),应优先用 instanceof 显式判断,而不是盲目转型:
if (payment instanceof Alipay) {
((Alipay) payment).useRedPacket(order);
}
但更推荐把这类行为抽成策略接口(如 RedPacketSupport),让 Alipay 实现它,其他子类返回空实现。否则一旦新增子类忘了重写该逻辑,就容易漏掉功能或抛 ClassCastException。
真正难的是设计初期就识别出哪些行为该抽象、哪些该收敛。很多系统后期“伪多态”——接口方法越来越多,子类大量返回 UnsupportedOperationException,说明抽象粒度错了。










