← 返回题目列表

什么是抽象工厂模式?它解决什么问题?

高频 简单 第 2 / 25 题 更新于 2026/07/28
抽象工厂模式创建型模式产品族设计模式

简化版

抽象工厂模式提供一个创建一组相关对象的接口,让调用方不依赖这些对象的具体类。它主要解决产品族的一致创建问题,避免系统里混用不兼容的一组产品。

详细版

抽象工厂的核心是“创建一整套相关产品”。例如跨平台 UI 中,Windows 风格需要 WindowsButton、WindowsCheckbox,Mac 风格需要 MacButton、MacCheckbox。调用方只依赖 UIFactory

interface UIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

class WindowsFactory implements UIFactory {
    public Button createButton() {
        return new WindowsButton();
    }

    public Checkbox createCheckbox() {
        return new WindowsCheckbox();
    }
}

业务代码拿到某个具体工厂后,就能创建同一产品族下的一组对象。这样可以保证 Windows 按钮和 Windows 复选框成套出现,Mac 组件也成套出现。

它适合产品族稳定、产品族之间需要整体切换的场景;不适合产品等级经常新增的场景,因为新增一个产品等级通常要修改抽象工厂接口和所有具体工厂。

完整版教学

一、抽象工厂的关键词是产品族

很多人会把抽象工厂理解成“更复杂的工厂”,这不够准确。它真正强调的是一组相关对象的创建一致性。

产品族可以理解为同一主题、同一平台、同一协议、同一厂商下的一套产品。比如 Windows UI 组件是一族,Mac UI 组件是一族;阿里云存储、队列、短信客户端可以是一族,AWS 对应客户端也是一族。

二、模式结构包括四类角色

抽象工厂模式通常包括:

  • 抽象工厂:声明创建一组产品的方法;
  • 具体工厂:创建某个产品族下的具体产品;
  • 抽象产品:声明每类产品的公共能力;
  • 具体产品:属于某个产品族的具体实现。

抽象工厂本身不直接执行业务逻辑,它负责把一组产品的创建规则收拢到同一个入口。

三、它解决的是混搭风险

如果调用方到处自己 new,就可能出现 WindowsButton 搭配 MacCheckbox 这种风格混乱的问题。抽象工厂让调用方先选择工厂,再通过同一个工厂创建整套产品,从结构上减少混搭。

这类问题在 UI、数据库方言、云厂商适配、消息中间件适配中都很常见。

四、它的代价是接口稳定性要求高

抽象工厂很适合新增产品族,比如新增 LinuxFactory。但如果要新增产品等级,比如 createMenu(),就要修改 UIFactory,并让所有具体工厂实现这个方法。

所以抽象工厂适合“产品族常扩展、产品等级相对稳定”的系统。

五、从“混搭会出错”推导模式结构

如果 WindowsButton 能与 MacCheckbox 任意组合且没有差异,抽象工厂价值有限。只有产品之间存在主题、协议、配置或兼容约束,混搭会造成错误时,选择一个 Factory 并从中取得整套产品才真正解决问题。

客户端 -> UIFactory
WindowsFactory -> WindowsButton
WindowsFactory -> WindowsCheckbox
MacFactory -> MacButton
MacFactory -> MacCheckbox
客户端只保存一个 Factory
同一 Factory 的多个 create 方法组成一族
具体产品类对客户端不可见

矩阵的每一行是一族兼容产品,每一列是一个产品等级。客户端选择一行对应的具体工厂,再从该工厂取得各列产品;如果允许调用方绕过工厂分别选择每个具体类,产品族一致性的结构性保证就消失了。

六、二维扩展成本与模式边界

评审维度本题结论
产品族不变量一次上下文中所有相关产品都由同一个具体工厂创建。
新增一行(产品族)新增一套具体产品和具体工厂,客户端仍依赖抽象。
新增一列(产品等级)修改抽象工厂和所有具体工厂,是模式的主要代价。
不应由工厂承担产品运行逻辑、跨对象业务编排和全局依赖查询。
退回更轻方案的条件一个产品等级用工厂方法;无混搭风险或实现固定时直接注入。

抽象工厂对所有变化并非都开放。它刻意固定列集合,以换取整行切换的一致性;如果系统最常发生的是新增列,工厂接口和所有行实现会频繁联动,此时应拆分工厂边界或选择组合方式。

七、落地验收清单

  1. 为每个具体工厂跑同一组契约测试,确认每个创建方法都返回正确产品等级。
  2. 给产品暴露 familyId() 仅用于测试,校验同一工厂创建的所有产品 familyId 一致。
  3. 加入一个假产品族,记录是否只新增一行实现和装配配置,而未修改旧工厂。
  4. 模拟新增一个产品等级,评估抽象接口和全部具体工厂的真实修改成本。
  5. 检查公共产品接口是否出现 AWS、MySQL、Windows 等具体实现词汇。
  6. 检查具体工厂是否只做组装与创建,没有吞入完整业务流程。
  7. 若产品持有连接或线程池,明确由工厂、容器还是调用方负责关闭。
  8. 若运行期按租户切换工厂,验证路由缓存、凭证刷新和租户隔离。

记忆钩子:抽象工厂不是“更抽象的 new”,而是“一次选择,整套一致”。

八、常见误区与追问

  • 误区:抽象工厂主要用于创建复杂单个对象。 复杂单对象分步构建更接近 Builder。
  • 误区:产品族只是多个同类实现。 同类实现构成产品等级,产品族跨越多个产品等级。
  • 误区:客户端可以知道具体产品类。 理想结构下客户端依赖抽象产品和抽象工厂。
  • 追问:模式有哪些角色? 抽象/具体工厂与抽象/具体产品四组角色。
  • 追问:为什么防止混搭? 客户端只选择一个具体工厂,各创建方法都返回该族实现。
  • 追问:适用的变化模式是什么? 产品族经常增加或整体切换,而产品等级集合相对稳定。

九、加强记忆

抽象工厂不是创建一个对象,而是创建一整套相关对象。看到“同一平台、同一风格、同一厂商的一组对象不能混搭”,就可以优先想到抽象工厂模式。