# 工厂模式和抽象工厂模式有什么区别?
Table of Contents
工厂模式和抽象工厂模式有什么区别?
工厂模式 vs 抽象工厂模式
【核心定义】
工厂模式是一种创建型设计模式,它定义一个用于创建对象的接口,但让子类决定实例化哪一个类;抽象工厂模式则提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
【关键要点】
-
目的不同
- 工厂模式:解决单个产品对象的创建问题,将对象的创建与使用分离。
- 抽象工厂模式:解决一系列相关产品族的创建问题,确保这些产品能够一起工作。
-
抽象层级不同
- 工厂模式:通常只有一个抽象产品接口和一个具体工厂类(或通过方法参数区分)。
- 抽象工厂模式:包含多个抽象产品接口(一个产品族)和一个抽象工厂接口,每个具体工厂负责创建一族产品。
-
扩展方向不同
- 工厂模式:扩展时新增具体产品类并修改工厂方法逻辑(或新增工厂子类),属于纵向扩展(增加产品种类)。
- 抽象工厂模式:扩展时新增具体工厂类实现整个产品族,属于横向扩展(增加产品族)。
【深度推导/细节】
核心矛盾:产品维度 vs 产品族维度
-
工厂模式的核心矛盾是如何将具体类的实例化延迟到子类。例如,一个日志记录器工厂,可能根据配置创建文件日志器或数据库日志器。它关注的是同一功能的不同实现(单个产品维度)。
-
抽象工厂模式的核心矛盾是如何保证一组相关产品能够协同工作。例如,GUI 组件工厂需要创建按钮、文本框、滚动条等一系列风格一致(如 Windows 风格或 Mac 风格)的组件。它关注的是多个相关产品的整体一致性(产品族维度)。
逻辑复现:抽象工厂的创建过程
Step 1:客户端代码仅依赖抽象工厂接口和抽象产品接口。
Step 2:在运行时,根据配置或环境决定使用哪个具体工厂(如 WindowsFactory 或 MacFactory)。
Step 3:通过该具体工厂创建一族产品(如 createButton(), createTextBox()),这些产品在风格和兼容性上得到保证。
Step 4:客户端使用这些抽象产品接口进行操作,与具体产品类解耦。
【关联/对比】
| 维度 | 工厂模式(含工厂方法模式) | 抽象工厂模式 |
|---|---|---|
| 核心职责 | 创建单一产品对象 | 创建一族相关产品对象 |
| 产品数量 | 通常一个工厂方法创建一个产品 | 一个工厂包含多个方法,创建多个产品 |
| 扩展复杂度 | 增加新产品需修改工厂逻辑或继承体系 | 增加新产品族只需新增具体工厂类,符合开闭原则 |
| 典型应用 | 连接器工厂、解析器工厂 | 跨平台 UI 组件库、数据库访问层(不同驱动族) |
与简单工厂的关联:简单工厂是工厂模式的简化,由一个工厂类通过条件判断创建不同产品,不符合开闭原则。工厂模式通过多态将判断逻辑分散到各个具体工厂中。
『面试官追问』
-
什么时候该用工厂模式,什么时候该用抽象工厂模式?
- 当系统中只有一个产品维度变化,且未来可能增加新产品类型时,使用工厂模式。
- 当系统中有多个相互关联的产品需要一起创建,并且这些产品有多个不同的系列(如不同主题、不同平台)时,使用抽象工厂模式。
-
抽象工厂模式如何保证产品族的兼容性?
- 通过将同一产品族的创建逻辑封装在同一个具体工厂类中。例如,
WindowsFactory只创建 Windows 风格的按钮和文本框,从源头上避免了风格混用。
- 通过将同一产品族的创建逻辑封装在同一个具体工厂类中。例如,
-
抽象工厂模式的缺点是什么?
- 难以支持新种类的产品:如果要在产品族中增加一个新产品(如新增“复选框”),需要修改抽象工厂接口及其所有具体工厂实现,违反了开闭原则。这被称为“抽象工厂的扩展性问题”。
-
能否结合使用这两种模式?
- 可以。例如,在抽象工厂的每个创建方法内部,可以使用工厂模式来创建具体的产品对象,以进一步解耦具体产品的实例化过程。
【直击痛点】
- “产品族”概念:这是理解抽象工厂的关键。产品族不是随意的一组产品,而是在特定上下文中必须一起使用、具有共同主题或约束的一组产品。例如,一套“现代风格”的家具(沙发、茶几、电视柜)就是一个产品族。
- 开闭原则的权衡:抽象工厂模式对增加新产品族是开放的(只需新增工厂类),但对增加新产品种类是封闭的(需要修改接口)。这是其设计的核心权衡,面试中需要明确指出。
【版本差异/模式变体】
- 经典 GoF 定义:抽象工厂模式强调接口,工厂方法模式常作为其实现基础。
- 现代应用:在依赖注入框架(如 Spring)中,
BeanFactory可视为工厂模式的升级应用;而配置一组相互依赖的 Bean 则可看到抽象工厂的思想。 - 简化趋势:结合反射和配置,可以设计更灵活的抽象工厂,减少新增产品族时的代码量。