抽象工厂模式线上出现问题时如何排查?
简化版
抽象工厂模式的核心是成套创建同一产品族对象。线上排查时不要只看某个具体产品对象,而要确认运行时选中了哪个具体工厂、创建了哪一组产品、产品族是否一致,以及配置、环境和依赖注入是否把错误工厂装配进来了。关键是先还原调用链、输入输出、状态变化和异常传播,再判断是哪层职责失守。
详细版
可以从 4 个角度回答:
- 先确认具体工厂选择逻辑是否正确;
- 再确认同一产品族里的对象是否成套创建;
- 接着检查配置、Profile、租户、渠道或运行环境是否影响工厂选择;
- 最后看异常是在创建阶段、调用阶段还是产品协作阶段发生。
抽象工厂常见于跨平台 UI、多云适配、多数据库驱动、主题皮肤等场景。它的风险包括产品族边界不清、新增产品等级成本高、抽象接口泄漏实现。线上问题通常不是“new 错一个类”这么简单,而是运行时条件、配置和产品族一致性共同出了问题。
排查时要保留工厂名称、产品族标识、请求上下文和关键配置快照。这样才能判断是工厂路由错了,还是具体产品实现本身有缺陷。
完整版教学
面试提示:设计模式排查题不要只说看日志,要讲清楚“运行时选了谁、创建了什么、协作是否一致、失败在哪里”这 4 件事。
一、先明确抽象工厂的排查对象
抽象工厂模式不是只创建一个对象,而是创建一组相关对象。
所以线上排查要看 3 层:
- 抽象工厂接口;
- 具体工厂实现;
- 具体产品族对象。
如果只盯着某个产品类,很容易漏掉“工厂选错导致整组产品不匹配”的问题。
二、先确认运行时选中了哪个工厂
排查第一步是还原工厂选择过程。
例如可以记录:
tenant = A
region = cn
factory = AliyunResourceFactory
storage = AliyunStorage
queue = AliyunQueue
如果预期是腾讯云产品族,却选中了阿里云工厂,那么后续产品对象再怎么查都只是现象。
三、检查产品族是否一致
抽象工厂最怕混用产品族。
比如存储对象来自厂商 A,消息队列对象来自厂商 B,单独看都能工作,但组合起来可能认证体系、地域、回调格式都不一致。
因此要检查创建结果是否满足同一产品族约束。
factory -> productA + productB + productC
all products must belong to the same family
这一步能定位很多灰度、配置和依赖注入错误。
四、检查配置和环境变量
具体工厂常由配置决定,比如 Profile、租户、渠道、地区、版本号、灰度开关。
排查时要看:
- 当前节点加载了哪个配置;
- 配置中心是否推送成功;
- 灰度规则是否命中;
- 默认工厂是否被误用;
- 多实例之间配置是否一致。
很多线上事故不是代码逻辑错,而是某些节点拿到了旧配置。
五、对比维度表
| 排查维度 | 应该看什么 | 常见问题 |
|---|---|---|
| 工厂选择 | 租户、环境、灰度、配置 | 选错具体工厂 |
| 产品族一致性 | 创建出来的一组产品 | 混用了不同产品族 |
| 生命周期 | 单例、原型、懒加载 | 初始化时机不一致 |
| 异常映射 | 创建异常和调用异常 | 异常被包装后语义丢失 |
| 可观测性 | 工厂名、产品名、traceId | 日志无法定位角色 |
这张表可以直接作为排查清单使用。
六、代码示例
下面是一个建议加在工厂选择处的诊断信息:
class FactorySelector {
AbstractFactory select(Context context) {
AbstractFactory factory = routeByTenant(context);
log.info("factory={}, tenant={}, region={}, traceId={}",
factory.name(), context.tenant(), context.region(), context.traceId());
return factory;
}
}
注意日志不要输出密钥、Token 或完整连接串,只输出能定位角色和配置版本的信息。
七、常见误区与追问
- 误区:只查具体产品类,不查工厂选择。 抽象工厂的问题经常发生在选择阶段。
- 误区:只在失败处打印异常。 失败处看到的是结果,工厂选择日志才是上游原因。
- 误区:忽略多节点配置差异。 灰度或配置中心异常会让不同机器选择不同工厂。
- 追问:如何证明产品族没有混用? 在创建后输出产品族标识,并在测试中断言一致性。
- 追问:如果只在部分租户失败怎么办? 先按租户维度查看工厂路由和配置版本。
- 追问:如何降低下次排查成本? 给工厂选择、产品创建和异常映射加结构化日志。
八、落地时的检查清单
上线前可以检查 5 项:
- 具体工厂名称是否能在日志中看到;
- 产品族标识是否一致;
- 默认工厂是否有明确兜底策略;
- 配置变更是否支持灰度和回滚;
- 创建失败和调用失败是否能区分。
这些检查能让抽象工厂从“看起来优雅”变成“线上可控”。
九、加强记忆
记住 4 个词:选择、成套、配置、证据。
选择决定用了哪个具体工厂。
成套决定产品族是否一致。
配置决定运行时为什么这样选。
证据决定线上能不能快速定位。
把这 4 点讲清楚,抽象工厂排查题就能回答得很完整。