多态参数和多态数组是提升代码可扩展性、降低修改成本的实用手段:用父类或接口类型接收子类对象,运行时自动调用各自实现;适用于多种相似行为(如导出、通知、任务执行)且变化点在“怎么做”的场景。

多态参数和多态数组不是炫技工具,而是让代码更易扩展、少改、少错的实用手段。核心就一条:用父类(或接口)类型接收不同子类对象,运行时自动调用各自实现的方法。
多态参数:一个方法处理多种业务类型
比如订单导出功能,要支持 Excel、PDF、CSV 三种格式。不使用多态时,可能写三个方法:exportToExcel()、exportToPdf()、exportToCsv(),每加一种格式就得新增方法、改调用方。
改成多态参数后,定义统一接口:
interface Exporter { void export(Order order); }各格式实现类分别实现该接口:
class ExcelExporter implements Exporter { public void export(Order order) { /* 写Excel逻辑 */ } }class PdfExporter implements Exporter { public void export(Order order) { /* 生成PDF逻辑 */ } }
业务方法只需声明一个参数:
void handleExport(Exporter exporter, Order order) { exporter.export(order); }调用时传入任意实现类实例即可:
handleExport(new ExcelExporter(), order);handleExport(new PdfExporter(), order);
- 新增格式?只写新实现类,不用动原有方法签名和调用逻辑
- 测试更聚焦:只要保证每个
Exporter实现符合契约,主流程无需重测 - 配合 Spring 等框架,还能通过注入自动切换策略,连 new 都省了
多态数组(或集合):批量操作异构对象,统一调度
想象后台要统一触发一批任务:发短信、发邮件、写日志、调第三方 API。它们动作不同,但都有“执行”这个共性。
定义任务接口:
interface Task { void execute(); String getType(); }各类任务实现它:
class SmsTask implements Task { public void execute() { sendSms(); } }class EmailTask implements Task { public void execute() { sendEmail(); } }
业务层可把不同任务放进同一集合:
Listfor (Task task : tasks) { task.execute(); }
- 添加新任务类型?只新增实现类,集合本身无需修改
- 可轻松叠加通用逻辑:比如统一加日志、异常兜底、超时控制,都写在循环里一次生效
- 结合工厂或配置,还能动态组装任务列表,比如根据订单状态决定执行哪些步骤
关键细节:别踩这几个坑
多态不是万能胶,用错反而增加理解成本:
-
别在多态对象里强行转型:比如
if (task instanceof SmsTask)—— 这说明设计没对齐,应把差异行为提到接口里 -
构造参数尽量保持一致:如果每个
Exporter构造所需参数差别很大,会削弱可替换性;可考虑用 Builder 或配置对象封装 -
接口职责要单一、稳定:比如
Exporter.export()只负责输出,别混入校验、组装、缓存等逻辑,否则子类容易违背里氏替换原则
什么时候该用?简单判断标准
遇到以下情况,多态参数/数组大概率是合适解法:
- 有多个类做相似的事(如:不同支付方式、不同通知渠道、不同解析器)
- 业务规则常变,但变化点集中在“怎么做”,而不是“要不要做”
- 你发现自己总在 if-else 或 switch 里不断加 case,且每个分支都 new 一个新对象
不复杂但容易忽略:真正节省的是后续每一次需求变更的成本。










