常见设计模式之工厂模式(golang)

5 阅读6分钟

工厂模式是创建型设计模式的核心成员,核心使命是  “封装对象的创建 / 获取逻辑,让客户端与具体对象的实现解耦” —— 简单说就是 “客户端不直接 new 对象,而是通过一个‘工厂’间接获取对象”。它的核心价值不是 “创建对象” 本身,而是 “隔离对象创建的复杂性”,让客户端只关心 “用什么”,不关心 “怎么造 / 怎么找”。

一、核心设计思想

工厂模式的本质是 “依赖抽象,不依赖具体”,通过三个关键组件实现解耦:

  1. 产品(Product) :被创建 / 获取的对象(可以是实体对象、解析器、适配器等),通常有统一的抽象接口(如 CGroupParser),保证客户端使用方式一致;
  2. 工厂(Factory) :负责对象的创建 / 获取逻辑(如判断类型、初始化参数、适配环境),是模式的核心;
  3. 客户端(Client) :只依赖抽象产品和工厂接口,不直接操作具体产品的创建,实现 “无感知切换产品”。

核心目标

  • 降低耦合:客户端无需知道产品的具体实现;
  • 简化维护:对象创建逻辑集中在工厂,修改时只需改工厂,无需改所有客户端;
  • 支持扩展:新增产品时,只需扩展工厂,无需修改现有客户端代码(符合 “开放 - 封闭原则”)。

工厂模式的三大分类

工厂模式不是单一模式,而是一个 “家族”,按复杂度和适用场景分为三类,核心区别在于 “工厂的抽象程度” 和 “支持的产品范围”:

简单工厂(Simple Factory)

  • 定义:一个工厂类(通常是工具类 / 静态类),根据输入参数(如类型、配置)直接返回对应的具体产品,无抽象工厂接口。

  • 核心特点

    • 结构最简单:只有 “具体工厂”+“抽象产品 + 具体产品” 两层;
    • 工厂是 “全能选手”:负责所有产品的创建逻辑,参数决定返回哪种产品;
    • 缺点:扩展产品时需修改工厂类(违背开放 - 封闭原则),适合产品类型少、稳定的场景。

工厂方法(Factory Method)

  • 定义:将简单工厂的 “全能逻辑” 拆分,为每个产品定义一个专属工厂(具体工厂),同时抽象出统一的工厂接口(抽象工厂)。客户端通过选择具体工厂,获取对应产品。

  • 核心特点

    • 一个工厂只负责一个产品;
    • 扩展灵活:新增产品时,只需新增 “具体产品 + 具体工厂”,无需修改现有代码;
    • 缺点:产品增多时,工厂类会泛滥(如 4 种产品对应 4 个工厂),适合 “单一产品等级结构”。
  • 核心对应关系:抽象工厂 → 具体工厂(N 个)→ 具体产品(N 个)(1:1 绑定)

抽象工厂(Abstract Factory)

  • 定义:抽象工厂接口定义 “一个产品族下所有产品等级的创建方法”,每个具体工厂对应一个产品族,负责创建该族下所有产品。

  • 核心特点

    • 聚焦 “产品族 + 产品等级” 双重区分:产品族、产品等级;
    • 一个工厂负责一个产品族的所有产品;
    • 优势:保证产品族内的一致性;
    • 缺点:扩展产品等级需修改抽象工厂接口和所有具体工厂(耦合产品等级),适合 “产品等级结构稳定” 的场景。
  • 核心对应关系:抽象工厂 → 具体工厂(N 个,对应 N 个产品族)→ 具体产品(N×M 个,对应 N 个产品族 × M 个产品等级)

三类工厂模式的对比表

维度简单工厂工厂方法抽象工厂
核心定位单一工厂 + 多产品多工厂 + 多产品(1:1)多工厂 + 多产品族(1:N)
抽象工厂接口有(定义单一产品创建)有(定义产品族创建)
扩展产品修改工厂类(违背开放封闭)新增 “产品 + 工厂”(无修改)新增产品族:无修改;新增产品等级:需修改所有工厂
适用场景产品少、稳定单一产品等级、需灵活扩展产品族 + 稳定产品等级、需保证族内一致性
复杂度极低中等较高
典型场景简单工具类创建(如日志器)单一类型产品扩展(如不同数据库连接)多类型组合产品(如版本 + 驱动、品牌 + 设备类型)

工厂模式的适用场景与不适用场景

适用场景

  1. 对象创建逻辑复杂:如需要判断环境、初始化参数、适配依赖;
  2. 客户端需解耦具体实现,只关心动作,而不关注实现;
  3. 需支持产品扩展或切换;
  4. 需保证产品一致性:如抽象工厂保证 “产品族只返回族内相关产品”。

不适用场景

  1. 产品简单且稳定:如只需要创建一个固定参数的对象(直接 new 更简洁);
  2. 产品等级频繁变动:如频繁新增 / 删除产品等级,抽象工厂会陷入 “修改爆炸”;
  3. 无需解耦客户端与产品:如小型工具类,客户端直接操作产品无维护成本。

核心误区澄清

  1. 误区:工厂模式只能 “创建新对象”→ 纠正:工厂模式的核心是 “获取对象”,对象可以是新创建的、对现有资源的封装(如解析器)、从配置 / 缓存中获取的,甚至是适配器转换的;
  2. 误区:工厂模式越复杂越好→ 纠正:优先选择简单方案(如简单工厂、策略映射),只有需要 “产品族一致性” 或 “多产品等级组合” 时,才用抽象工厂;
  3. 误区:工厂模式必须用类继承→ 纠正:Go 语言中无需类继承,通过 “接口 + 结构体” 即可实现(如抽象工厂是接口,具体工厂是实现该接口的结构体)。

总结

工厂模式的核心是 “封装创建逻辑,解耦客户端与具体实现”,三类子模式分别对应不同复杂度的场景:

  • 简单工厂:适合简单场景,追求简洁;
  • 工厂方法:适合单一产品等级的灵活扩展;
  • 抽象工厂:适合 “产品族 + 稳定产品等级” 的双重区分场景。

使用时的核心原则: “能简单不复杂” —— 如果不需要 “产品族” 或 “多产品等级”,优先用简单工厂或策略映射(非创建型方案),只有场景匹配时才用抽象工厂。