抽象工厂模式的优缺点是什么?
简化版
抽象工厂的优点是隔离具体产品类、保证产品族一致性、方便整体切换实现;缺点是结构较重,新增产品等级会牵动所有具体工厂。它适合产品族变化多、产品等级相对稳定的系统。
详细版
主要优点:
- 调用方依赖抽象产品和抽象工厂,减少对具体类的依赖;
- 同一具体工厂创建同一产品族,避免产品混搭;
- 新增产品族时扩展比较自然;
- 创建逻辑集中在具体工厂,便于替换、测试和配置管理。
主要缺点:
- 类和接口数量增加,理解成本更高;
- 新增产品等级要修改抽象工厂和所有具体工厂;
- 产品族边界设计不好时,工厂接口容易膨胀;
- 过度使用会让简单对象创建变得绕。
面试回答要结合适用条件,不要只说“解耦、符合开闭原则”。抽象工厂只是在新增产品族时更符合开闭原则,对新增产品等级并不友好。
完整版教学
一、优点一:隔离具体实现
业务代码只依赖 UIFactory、Button、Checkbox 等抽象,不直接依赖 WindowsButton 或 MacCheckbox。这让替换整套实现变得更容易。
测试时也可以注入一个 FakeFactory,创建一组测试产品。
二、优点二:保证产品族一致性
抽象工厂最有辨识度的优点就是防止混搭。同一个具体工厂产出的产品天然属于同一族。
这比让调用方分别选择每个产品实现更稳,因为调用方不需要理解每个具体产品之间的兼容关系。
三、缺点一:新增产品等级成本高
一旦抽象工厂接口增加 createMenu(),所有具体工厂都必须跟着改。这一点在产品等级频繁变化时会很痛。
所以抽象工厂的前提是产品等级比较稳定,否则后续维护成本会偏高。
四、缺点二:抽象边界难设计
产品族拆得太细,工厂数量会膨胀;产品族拆得太粗,接口会混乱。抽象工厂的难点不是代码写法,而是边界判断。
工程中要围绕真实变化点抽象,而不是为了套模式硬拆。
五、用三平台两组件量化收益和代价
有 Windows、Mac、Linux 三族和 Button、Checkbox 两个等级时,增加 Linux 只新增一行;增加 Menu 则要改工厂接口并补三套实现。这个 3×2 矩阵清楚展示抽象工厂为何“加族容易、加等级困难”。
Button Checkbox
Windows WinButton WinCheckbox
Mac MacButton MacCheckbox
新增 Linux 行: LinButton + LinCheckbox + LinuxFactory
新增 Menu 列: 修改 UIFactory
Win/Mac/Linux Factory 全部增加 createMenu()
产品族一致性换来列扩展成本
矩阵的每一行是一族兼容产品,每一列是一个产品等级。客户端选择一行对应的具体工厂,再从该工厂取得各列产品;如果允许调用方绕过工厂分别选择每个具体类,产品族一致性的结构性保证就消失了。
六、二维扩展成本与模式边界
| 评审维度 | 本题结论 |
|---|---|
| 产品族不变量 | 客户端从同一 UIFactory 取得的组件风格一致。 |
| 新增一行(产品族) | 增加具体产品一套和具体工厂一个,原接口与旧族稳定。 |
| 新增一列(产品等级) | 接口新增方法并修改 N 个具体工厂,成本随产品族数量增长。 |
| 不应由工厂承担 | 组件渲染流程、页面布局业务和状态同步。 |
| 退回更轻方案的条件 | 产品等级频繁变化时拆成独立小工厂或使用组合注册。 |
抽象工厂对所有变化并非都开放。它刻意固定列集合,以换取整行切换的一致性;如果系统最常发生的是新增列,工厂接口和所有行实现会频繁联动,此时应拆分工厂边界或选择组合方式。
七、落地验收清单
- 为每个具体工厂跑同一组契约测试,确认每个创建方法都返回正确产品等级。
- 给产品暴露
familyId()仅用于测试,校验同一工厂创建的所有产品 familyId 一致。 - 加入一个假产品族,记录是否只新增一行实现和装配配置,而未修改旧工厂。
- 模拟新增一个产品等级,评估抽象接口和全部具体工厂的真实修改成本。
- 检查公共产品接口是否出现 AWS、MySQL、Windows 等具体实现词汇。
- 检查具体工厂是否只做组装与创建,没有吞入完整业务流程。
- 若产品持有连接或线程池,明确由工厂、容器还是调用方负责关闭。
- 若运行期按租户切换工厂,验证路由缓存、凭证刷新和租户隔离。
记忆钩子:收益是整行切换,代价是新增一列要补全所有行。
八、常见误区与追问
- 误区:抽象工厂在所有方向都符合开闭原则。 它主要对新增产品族开放,对新增产品等级不友好。
- 误区:保证产品族一致性只是一种命名约定。 客户端只持有一个具体工厂时,创建入口从结构上约束了来源。
- 误区:类数量增加没有成本。 接口、具体产品和具体工厂都会增加理解与测试负担。
- 追问:最核心优点是什么? 隔离具体类并确保一组相关产品成套创建与整体替换。
- 追问:最核心缺点是什么? 产品等级集合被固化,新增等级牵动所有具体工厂。
- 追问:何时不值得使用? 产品少、无混搭风险或产品等级变化远快于产品族时。
九、加强记忆
抽象工厂的优点集中在“成套创建、整体切换”,缺点集中在“新增一类产品很麻烦”。回答优缺点时带上产品族和产品等级,答案就不会空。