多态是运行时按类型自动选行为,配置加载器通过抽象接口ConfigLoader统一load和supports方法,子类专注解析逻辑,注册表替代硬编码工厂,模板方法封装初始化流程,避免instanceof和强制转型。

多态不是让代码看起来“有接口”,而是让运行时真正按类型自动选行为。配置项加载器要支持多种格式(如 properties、JSON、YAML),关键不是写一堆 if-else 判断后缀,而是把“怎么加载”这件事交给子类决定,上层只管调用统一方法。
定义统一加载契约,屏蔽格式差异
声明一个抽象的 ConfigLoader 接口或抽象类,只暴露核心能力:
-
load(String path):返回通用配置结构(比如
Map<String, Object>或自定义ConfigData) - supports(String fileName):判断是否能处理该文件(仅靠后缀或魔数,不读内容、不查配置)
所有具体加载器(PropertiesLoader、JsonLoader、YamlLoader)都实现它,并各自专注自己的解析逻辑——Properties 用 Properties.load(),JSON 用 Jackson,YAML 用 SnakeYAML。客户端完全不用知道背后是哪种格式。
用注册表替代硬编码工厂
避免在工厂里写 if ("json".equals(ext)) return new JsonLoader()。启动时扫描所有 ConfigLoader 实现类,按 @Supports("json") 注解或类名规则(如 JsonConfigLoader)自动注册到 ConcurrentHashMap<String, Supplier<ConfigLoader>>:
立即学习“Java免费学习笔记(深入)”;
- 调用时只传语义标识(如
"json"),不传类名全路径 - 新增格式只需加一个类 + 注解,零改动现有工厂代码
- 高并发下注册一次,后续查表快且线程安全
让加载流程本身也多态化
不同格式初始化步骤相似(打开 → 读取 → 解析 → 关闭),但细节不同。可用模板方法封装主干,把差异点下沉为抽象方法:
-
InputStream open(String path):Properties 用getResourceAsStream,JSON 可能走 HTTP 流 -
Object parse(InputStream in):各子类用对应库解析,返回统一结构 -
void close(InputStream in):统一资源释放,避免泄漏
这样业务代码调用 loader.load("app.json") 时,JVM 自动路由到 JsonLoader 的三个钩子方法,无需 instanceof 或转型。
警惕多态没走通的典型信号
如果出现以下情况,说明多态被绕过了:
- 业务层写了
if (loader instanceof JsonLoader)或强制转型 - 工厂类被 new 在 Service 里,而不是通过构造器注入
- 配置里传的是
"com.example.JsonLoader"这种类名,而不是"json"
真正的多态,是让类型选择发生在运行时,且对使用者完全透明。配置加载这件事,本就不该让业务代码操心格式细节。


















