首页/开发/代码质量与评审速查/抽象工厂 Abstract Factory(创建型)
设计原则与模式62 条

抽象工厂 Abstract Factory(创建型)

创建一族相关产品(同一风格的按钮 + 输入框 + 滚动条):产品族内保证一致,风格切换只换工厂实现;产品种类增加时接口需同步扩展,注意这一耦合。

抽象工厂是什么

为一族相关产品提供创建接口:同一风格下的按钮、输入框、滚动条由同一个工厂产出,产品族内部保持一致,切换风格时只换工厂实现。它的关键在于「族」——产品之间需要搭配使用;如果只是创建单个对象,工厂方法或静态工厂就够了。代价是新增一种产品种类时,所有工厂实现都要跟着改。

基本信息

意图一致产品族的创建接口
适合多套外观、驱动或方言并存
代价新增产品种类要改所有工厂实现
相关工厂方法、静态工厂、原型(可缓存产品实例)

典型使用场景

  • 跨平台界面:同一平台下的控件必须搭配,不能混用两套风格
  • 多数据库方言:同一批 DAO 实现必须属于同一种方言
  • 主题与皮肤:主题切换时所有组件同时更换
  • 测试替身:把整套协作者替换成内存实现,一次切换整族
  • 多租户配置:不同租户使用不同实现组合,但调用方接口一致

结构示意(Java)

结构示意(Java)
interface GuiFactory {
    Button button();
    Checkbox checkbox();
}

class MacFactory implements GuiFactory {
    @Override public Button button()     { return new MacButton(); }
    @Override public Checkbox checkbox() { return new MacCheckbox(); }
}

class WinFactory implements GuiFactory { /* 同上的 Windows 实现 */ }

// 调用方只持有工厂接口,切换风格只换注入的实现
class Form {
    private final GuiFactory factory;   // 构造注入
    Form(GuiFactory factory) { this.factory = factory; }
    Button submit() { return factory.button(); }
}

与其它创建方式对比

方式产出适用
抽象工厂一族相关产品族内需要保持一致
工厂方法单一产品子类决定创建哪种实现
静态工厂方法单一产品语言层面替代构造器
依赖注入容器按配置装配的整对象图产品族由配置决定
抽象工厂常与依赖注入容器并存:容器负责选择并注入哪个工厂实现,工厂负责保证族内一致。两者职责不同,不必二选一。
产品族只有一套且短期不会有第二套时,这层抽象属于过度设计:多出的接口与实现类换不来任何灵活性,删除成本还很高。判断依据是「是否真的存在多套需要整体切换的实现」。

易错点

  • 产品族只有一套:抽象层属于过度设计,多出的类型只增加理解成本
  • 族内产品可以跨风格混用:一致性保证被绕过,混搭出意料之外的行为
  • 新增产品种类时改所有工厂:接口扩展的代价被低估,改动面扩散到每个实现
  • 把业务规则写进工厂:创建逻辑承担了不该有的判断,工厂逐渐变成上帝类

数据来源与参考

  • 《设计模式》(GoF)· Abstract Factory
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌