多态是Java实现解耦与灵活替换的核心机制,通过接口定义行为契约、父类引用指向子类对象、配合工厂或Spring容器集中管理实例化,使业务代码零修改即可替换实现;static、final、private及构造方法无法参与多态,应避免作为扩展点。

多态是 Java 中实现解耦与灵活替换最自然、最常用的方式。它的核心不在于“写得多”,而在于“依赖得少”——让调用方只关心行为契约,不关心具体是谁在干活。
用接口定义统一行为,屏蔽实现差异
解耦的第一步是把“做什么”和“怎么做”分开。比如日志功能,不直接 new FileLogger() 或 ConsoleLogger(),而是先定义一个接口:
- Logger 接口只声明 log(String msg),不提供任何实现
- FileLogger 和 ConsoleLogger 各自实现该接口,内部逻辑互不影响
- 业务类(如 UserService)只依赖 Logger 接口,不持有任何具体实现类
这样,替换日志方式时,只需改一行注入代码(如 Spring 中更换 @Bean),业务代码零修改。
父类引用 + 子类对象,运行时决定行为
多态生效的关键语法是“父类(或接口)引用指向子类对象”。例如:
立即学习“Java免费学习笔记(深入)”;
- Payment processor = new AlipayPayment();
- processor.pay(100); // 实际调用 AlipayPayment 的 pay 方法
- 换成 new WechatPayment(),同一行调用自动走微信逻辑
编译时只知道它是 Payment 类型,运行时才确定执行哪个子类方法——这正是“编译期不依赖,运行时才依赖”的体现。
配合工厂或 Spring 容器,集中管理替换点
硬编码 new 子类仍存在局部耦合。更进一步的做法是把对象创建抽离:
- 自定义简单工厂:根据配置返回不同 Payment 实现
- Spring 中用 @Qualifier 或 profile 控制 Bean 实例化
- 甚至结合策略模式,用 Map<String, Payment> 按类型名动态获取
所有替换逻辑集中在一处,新增支付方式只需加实现类+注册,完全不影响已有调用链。
避开不能多态的陷阱,保证可替换性
不是所有方法都能被重写,也就无法参与多态。以下方法无法体现多态特性,应避免作为关键扩展点:
- static 方法:属于类,不随对象变化
- final 方法:子类无法重写
- private 方法:子类不可见,更谈不上重写
- 构造方法:本身就不支持重写
设计接口或抽象父类时,把需要灵活替换的行为声明为 public、非 final、非 static 的实例方法。


















