核心是用抽象类型作返回值,子类重写实现差异化行为:定义统一接口或抽象类(优先接口),工厂方法返回抽象类型,子类各自实现关键逻辑,运行时通过父类引用调用子类方法实现多态。

核心在于:用抽象类型作返回值,靠子类重写实现差异化行为,工厂只管“给谁”,不操心“怎么干”。
定义清晰的抽象基类或接口
这是多态的前提。必须有一个统一的顶层契约,比如抽象类 Exporter 或接口 TaskExecutor,里面声明公共方法(如 execute()、validate()),但不提供具体实现。
- 推荐优先用接口——更轻量,避免单继承限制,也更符合“只约行为、不绑结构”的设计意图
- 抽象类适合有共用字段或默认逻辑的场景,但要确保子类确实需要继承它,而不是被迫套壳
- 所有具体子类必须显式
extends或implements,不能靠“看起来像”来蒙混,JVM/CLR 只认语法层面的继承关系
工厂方法返回抽象类型,而非具体类
工厂类(或工厂方法)的返回类型必须是上面定义的抽象类型,例如 public Exporter createExporter(String type),而不是 FileExporter 或 ApiExporter。
- 调用方拿到的是 Exporter 引用,后续所有操作(如
export())都走运行时绑定,自动调用实际子类的方法 - 新增子类时,只需扩展工厂内部判断逻辑(如加一个
else if ("cloud")分支),原有业务代码完全不动 - 避免返回
Object或泛型裸类型,否则强转风险高,失去多态保护
子类各自实现关键行为,互不干扰
每个具体子类负责自己那块逻辑,比如 FileExporter.export() 写本地文件,CloudExporter.export() 调 API 上传——它们都实现了同一个方法签名,但内部完全不同。
- 方法体里不要做跨子类通用的事(如日志、重试),这些应抽到工具类或装饰器中
- 避免在子类里覆盖父类非 abstract 方法,除非明确知道后果;更别在接口里塞 default 方法来承担业务逻辑
- 如果子类间有共用初始化流程,可放在抽象基类的构造函数里,由
super()统一触发
运行时靠引用类型决定行为归属
最终生效的关键一步:用父类/接口引用指向子类实例。例如 Exporter e = factory.createExporter("api"); e.export(); —— 这行 e.export() 看似调用接口方法,实际执行的是 ApiExporter 的版本。
- 这个绑定发生在运行期,编译期只校验方法是否存在,不关心具体实现
- 调试时能看到变量类型显示为
Exporter,但实际对象是ApiExporter@1a2b3c,这就是多态在起作用 - 没有这一步,工厂返回再灵活也没用:如果写成
ApiExporter e = ...,那就又和具体类耦合了











