什么是工厂模式?3种实现方式的区别和特点?
2026年01月27日
一则或许对你有用的小广告
欢迎 加入小哈的星球 ,你将获得: 专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新开坑项目: 《Spring AI 项目实战(问答机器人、RAG 增强检索、联网搜索)》 正在持续爆肝中,基于
Spring AI + Spring Boot3.x + JDK 21..., 点击查看; - 《从零手撸:仿小红书(微服务架构)》 已完结,基于
Spring Cloud Alibaba + Spring Boot3.x + JDK 17..., 点击查看项目介绍; 演示链接: http://116.62.199.48:7070/; - 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/
面试考察点
当面试官提出这个问题时,他不仅仅是在考察你是否背下了设计模式的定义,更是在评估你的以下几个维度的能力:
- 对面向对象设计原则的理解:你是否理解 “封装变化”、“针对接口编程” 等原则,并能将其应用于解耦对象创建逻辑。
- 对不同场景下解决方案的区分能力:三种工厂模式解决的是不同复杂度、不同维度的 “对象创建” 问题,能否准确区分是关键。
- 对设计模式演进脉络的掌握:从简单工厂到工厂方法再到抽象工厂,体现了设计模式是如何随着需求复杂度的增加而演进的。
- 实践经验与场景化思维:你是否能在实际项目中识别出需要使用工厂模式的场景,并选择合适的一种。
核心答案
工厂模式 是一种创建型设计模式,其核心思想是将对象的创建过程封装起来,让客户端不直接依赖具体实现类,而是依赖一个抽象的创建接口,从而实现解耦。
三种主要的实现方式及其核心区别如下:
- 简单工厂模式 (Simple Factory):一个工厂类根据传入的参数,通过
if/else或switch来创建并返回不同的产品对象。它不属于 GoF 23 种设计模式,更像是一种编程习惯。 - 工厂方法模式 (Factory Method):定义一个用于创建对象的接口(抽象工厂),但让子类决定实例化哪一个具体产品类。工厂方法使一个类的实例化延迟到其子类。核心是 “类的” 解耦。
- 抽象工厂模式 (Abstract Factory):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。核心是“产品族”的创建,比工厂方法的维度更高。
简单比喻:
- 简单工厂:一个万能工具,按按钮出不同工具。
- 工厂方法:各家工具店(子类)都承诺能提供锤子(产品接口),但A店出木工锤,B店出石工锤。
- 抽象工厂:一个家具厂(抽象工厂)承诺能生产一整套现代风格家具(产品族);另一个家具厂则生产一整套古典风格家具。
深度解析
原理/机制与代码示例
1. 简单工厂模式
它负责集中处理所有产品的创建逻辑。当新增产品时,必须修改工厂类的代码(增加 if/else),这违反了开闭原则。
// 产品接口
interface Chart {
void display();
}
// 具体产品
class LineChart implements Chart { /* ... */ }
class PieChart implements Chart { /* ... */ }
// 简单工厂
public class ChartFactory {
public static Chart getChart(String type) {
if (type.equalsIgnoreCase("line")) {
return new LineChart();
} else if (type.equalsIgnoreCase("pie")) {
return new PieChart();
}
throw new IllegalArgumentException("Unsupported chart type.");
}
}
// 客户端使用
Chart chart = ChartFactory.getChart("line");
chart.display();
2. 工厂方法模式 它将具体产品的创建延迟到子类。每新增一个产品,就新增一个对应的具体工厂类,符合开闭原则。
// 抽象工厂
interface ChartFactory {
Chart createChart();
}
// 具体工厂
class LineChartFactory implements ChartFactory {
@Override
public Chart createChart() {
return new LineChart(); // 专注创建LineChart
}
}
class PieChartFactory implements ChartFactory {
@Override
public Chart createChart() {
return new PieChart(); // 专注创建PieChart
}
}
// 客户端使用
ChartFactory factory = new LineChartFactory();
Chart chart = factory.createChart(); // 创建的是LineChart
chart.display();
3. 抽象工厂模式 它用于创建产品族(一系列相关的产品)。一个抽象工厂定义能创建哪些产品,每个具体工厂负责一个产品族的具体实现。
// 抽象产品族:UI组件
interface Button { void render(); }
interface TextField { void input(); }
// 抽象工厂:能创建一套UI组件
interface UIFactory {
Button createButton();
TextField createTextField();
}
// 具体产品族1:Mac风格
class MacButton implements Button { /* ... */ }
class MacTextField implements TextField { /* ... */ }
class MacUIFactory implements UIFactory {
public Button createButton() { return new MacButton(); }
public TextField createTextField() { return new MacTextField(); }
}
// 具体产品族2:Windows风格
class WinButton implements Button { /* ... */ }
class WinTextField implements TextField { /* ... */ }
class WinUIFactory implements UIFactory {
public Button createButton() { return new WinButton(); }
public TextField createTextField() { return new WinTextField(); }
}
// 客户端使用:轻松切换整套UI风格
UIFactory factory = new MacUIFactory(); // 只需改这一行
Button btn = factory.createButton(); // 得到Mac风格按钮
TextField field = factory.createTextField(); // 得到Mac风格输入框
对比分析与适用场景
| 特性 | 简单工厂 | 工厂方法 | 抽象工厂 |
|---|---|---|---|
| 核心角色 | 工厂类、产品接口、具体产品 | 抽象工厂、具体工厂、产品接口、具体产品 | 抽象工厂、具体工厂、抽象产品族、具体产品族 |
| 扩展性 | 差(需修改工厂类) | 好(新增产品+工厂类) | 好(新增产品族+工厂类) |
| 复杂度 | 低 | 中 | 高 |
| 遵循开闭原则 | 否 | 是 | 是 |
| 解决问题维度 | 单个产品的创建选择 | 单个产品的创建延迟与扩展 | 多个相关产品(产品族) 的成套创建 |
| 典型应用场景 | JDK Calendar.getInstance(), NumberFormat.getInstance() | Spring Framework 中的 BeanFactory, 日志框架的 AppenderFactory | 跨平台UI库, 数据库访问层(连接、命令、适配器等组件的统一切换) |
最佳实践与常见误区
-
最佳实践:
- 优先使用工厂方法:在大多数需要解耦对象创建的场景下,工厂方法模式是更优雅、更符合设计原则的选择。
- 理解抽象工厂的 “产品族”:不要滥用抽象工厂。只有当系统中存在多个产品等级结构(如不同操作系统下的按钮、文本框、菜单),并且你希望一次性地使用同一个产品族中的产品时,才考虑它。
- 结合依赖注入(DI):现代框架(如 Spring)的 IoC 容器本质上是超级工厂,它利用工厂模式的思想,通过配置和注解来管理和创建所有 Bean,这是工厂模式在生产环境中的终极实践。
-
常见误区:
- 混淆工厂方法与抽象工厂:记住,工厂方法关注 “一个产品” 的创建扩展;抽象工厂关注 “一系列产品” 的创建和组合。
- 为了模式而模式:如果产品创建逻辑非常简单,直接使用
new是最清晰的选择。引入模式会带来额外的抽象层,增加复杂度。 - 认为简单工厂一无是处:虽然它不符合开闭原则,但在内部工具类、创建逻辑稳定且简单的场景下,它代码直观,完全可以使用。
总结
工厂模式的本质是通过引入一个抽象层来封装对象的创建过程,从而实现客户端代码与具体产品类的解耦。简单工厂易于理解但扩展性差;工厂方法通过子类化解决了扩展问题;而抽象工厂则将解耦的维度从 “单个产品” 提升到了 “产品族”,是构建大型、可配置系统(如 UI 框架、ORM)的利器。