news 2026/5/7 11:40:21

设计模式——抽象工厂模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
设计模式——抽象工厂模式

抽象工厂模式 (Abstract Factory Pattern)

什么是抽象工厂模式?

抽象工厂模式是一种创建型设计模式,它提供一个接口,用于创建相关或依赖对象族,而无需指定它们具体的类。

简单来说:抽象工厂模式就是创建一系列相关的对象,而不是单个对象。

生活中的例子

想象一家家具制造厂

  • 产品族:现代风格家具、古典风格家具
  • 产品等级:椅子、沙发、桌子
风格椅子沙发桌子
现代风格现代椅子现代沙发现代桌子
古典风格古典椅子古典沙发古典桌子

抽象工厂模式可以确保:

  • 现代风格的椅子、沙发、桌子搭配在一起
  • 古典风格的椅子、沙发、桌子搭配在一起
  • 不会出现现代椅子配古典沙发的情况

为什么需要抽象工厂模式?

工厂方法模式的局限

工厂方法模式只能创建一种类型的产品。如果需要创建多个相关产品,就需要多个工厂,这样会导致:

  1. 工厂类数量爆炸:每种产品都需要一个工厂
  2. 产品族无法保证一致性:可能创建出不匹配的产品组合

抽象工厂模式的优势

  1. 产品族一致性:确保创建的产品属于同一个产品族
  2. 代码解耦:客户端不需要知道具体创建的是哪个产品族
  3. 易于扩展:新增产品族时,只需新增对应的工厂类

抽象工厂模式的结构

┌─────────────────────────┐ │ AbstractFactory │ 抽象工厂 ├─────────────────────────┤ │ + createProductA(): A │ │ + createProductB(): B │ │ + createProductC(): C │ └──────────┬──────────────┘ │ 继承 ├──┬──────────────────┬──────────────┐ │ │ │ ┌──────────┴──────────┐ ┌───────┴───────────┐ ┌───┴────────┐ │ ConcreteFactory1 │ │ ConcreteFactory2 │ │ ... │ 具体工厂 └─────────────────────┘ └───────────────────┘ └────────────┘ ┌─────────────────────────┐ │ AbstractProductA │ 抽象产品A ├─────────────────────────┤ │ + operation(): void │ └──────────┬──────────────┘ │ 继承 ├──┬──────────────────┬──────────────┐ │ │ │ ┌──────────┴──────────┐ ┌───────┴───────────┐ ┌───┴────────┐ │ ProductA1 │ │ ProductA2 │ │ ... │ 具体产品A └─────────────────────┘ └───────────────────┘ └────────────┘ ┌─────────────────────────┐ │ AbstractProductB │ 抽象产品B ├─────────────────────────┤ │ + operation(): void │ └──────────┬──────────────┘ │ 继承 ├──┬──────────────────┬──────────────┐ │ │ │ ┌──────────┴──────────┐ ┌───────┴───────────┐ ┌───┴────────┐ │ ProductB1 │ │ ProductB2 │ │ ... │ 具体产品B └─────────────────────┘ └───────────────────┘ └────────────┘

代码示例

1. 定义抽象产品

// 抽象产品:形状接口publicinterfaceShape{/** * 绘制形状 */voiddraw();}// 抽象产品:颜色接口publicinterfaceColor{/** * 填充颜色 */voidfill();}

2. 定义具体产品

// 具体产品:圆形publicclassCircleimplementsShape{@Overridepublicvoiddraw(){System.out.println("绘制圆形");}}// 具体产品:矩形publicclassRectangleimplementsShape{@Overridepublicvoiddraw(){System.out.println("绘制矩形");}}// 具体产品:正方形publicclassSquareimplementsShape{@Overridepublicvoiddraw(){System.out.println("绘制正方形");}}// 具体产品:红色publicclassRedimplementsColor{@Overridepublicvoidfill(){System.out.println("填充红色");}}// 具体产品:绿色publicclassGreenimplementsColor{@Overridepublicvoidfill(){System.out.println("填充绿色");}}// 具体产品:蓝色publicclassBlueimplementsColor{@Overridepublicvoidfill(){System.out.println("填充蓝色");}}

3. 定义抽象工厂

/** * 抽象工厂:形状和颜色工厂 * 定义了创建形状和颜色的抽象方法 */publicinterfaceAbstractFactory{/** * 创建形状 * @param shapeType 形状类型 * @return 形状实例 */ShapegetShape(StringshapeType);/** * 创建颜色 * @param colorType 颜色类型 * @return 颜色实例 */ColorgetColor(StringcolorType);}

4. 定义具体工厂

/** * 具体工厂:形状工厂 * 负责创建各种形状 */publicclassShapeFactoryimplementsAbstractFactory{@OverridepublicShapegetShape(StringshapeType){if(shapeType==null){returnnull;}if(shapeType.equalsIgnoreCase("CIRCLE")){returnnewCircle();}elseif(shapeType.equalsIgnoreCase("RECTANGLE")){returnnewRectangle();}elseif(shapeType.equalsIgnoreCase("SQUARE")){returnnewSquare();}returnnull;}@OverridepublicColorgetColor(StringcolorType){// 形状工厂不负责创建颜色returnnull;}}/** * 具体工厂:颜色工厂 * 负责创建各种颜色 */publicclassColorFactoryimplementsAbstractFactory{@OverridepublicShapegetShape(StringshapeType){// 颜色工厂不负责创建形状returnnull;}@OverridepublicColorgetColor(StringcolorType){if(colorType==null){returnnull;}if(colorType.equalsIgnoreCase("RED")){returnnewRed();}elseif(colorType.equalsIgnoreCase("GREEN")){returnnewGreen();}elseif(colorType.equalsIgnoreCase("BLUE")){returnnewBlue();}returnnull;}}

5. 定义工厂生产者

/** * 工厂生产者:工厂创建器 * 根据传入的类型返回相应的工厂 */publicclassFactoryProducer{/** * 获取工厂 * @param choice 工厂类型 * @return 工厂实例 */publicstaticAbstractFactorygetFactory(Stringchoice){if(choice.equalsIgnoreCase("SHAPE")){returnnewShapeFactory();}elseif(choice.equalsIgnoreCase("COLOR")){returnnewColorFactory();}returnnull;}}

6. 使用工厂

/** * 抽象工厂模式演示类 * 演示如何使用抽象工厂模式创建形状和颜色 */publicclassAbstractFactoryPatternDemo{publicstaticvoidmain(String[]args){System.out.println("=== 抽象工厂模式演示 - 形状和颜色 ===\n");// 获取形状工厂AbstractFactoryshapeFactory=FactoryProducer.getFactory("SHAPE");// 获取颜色工厂AbstractFactorycolorFactory=FactoryProducer.getFactory("COLOR");// 创建形状System.out.println("--- 绘制形状 ---");Shapeshape1=shapeFactory.getShape("CIRCLE");shape1.draw();Shapeshape2=shapeFactory.getShape("RECTANGLE");shape2.draw();Shapeshape3=shapeFactory.getShape("SQUARE");shape3.draw();// 创建颜色System.out.println("\n--- 填充颜色 ---");Colorcolor1=colorFactory.getColor("RED");color1.fill();Colorcolor2=colorFactory.getColor("GREEN");color2.fill();Colorcolor3=colorFactory.getColor("BLUE");color3.fill();System.out.println("\n=== 抽象工厂模式的优势 ===");System.out.println("1. 产品族一致性:可以创建相关的对象族");System.out.println("2. 代码解耦:客户端不需要知道具体创建的是哪个产品");System.out.println("3. 易于扩展:新增产品族时,只需新增对应的工厂类");System.out.println("\n=== 实际应用场景 ===");System.out.println("1. UI组件库:不同风格的按钮、文本框、菜单");System.out.println("2. 数据库访问:不同数据库的连接、命令、参数");System.out.println("3. 游戏开发:不同风格的道具、角色、场景");System.out.println("4. 配置管理:不同环境的配置对象");System.out.println("\n=== 与工厂方法的区别 ===");System.out.println("工厂方法:创建单个对象");System.out.println("抽象工厂:创建对象族(多个相关对象)");System.out.println("\n=== 扩展性说明 ===");System.out.println("新增形状:只需在ShapeFactory中添加新的形状类");System.out.println("新增颜色:只需在ColorFactory中添加新的颜色类");System.out.println("新增产品族:需要修改AbstractFactory接口和所有工厂类");}}

抽象工厂模式的优点

  1. 产品族一致性:确保创建的产品属于同一个产品族
  2. 代码解耦:客户端与具体产品解耦
  3. 易于扩展:新增产品族时,只需新增对应的工厂类
  4. 符合开闭原则:对扩展开放,对修改关闭

抽象工厂模式的缺点

  1. 扩展困难:新增产品等级(新增产品类型)需要修改所有工厂类
  2. 类数量爆炸:每增加一个产品族,就需要增加多个产品类
  3. 系统复杂度增加:引入了多个抽象层,增加了系统的理解难度

适用场景

  1. 需要创建产品族:需要创建一系列相关的对象
  2. 产品族需要一致性:确保创建的产品属于同一个产品族
  3. 系统独立于产品的创建:客户端不依赖具体产品的创建细节
  4. 多个产品族:系统有多个产品族,且产品族可能继续增加

常见应用场景

  • 跨平台UI开发:Windows风格、Mac风格、Linux风格
  • 数据库访问:MySQL、Oracle、PostgreSQL的连接和命令
  • 游戏开发:不同风格的道具、角色、场景
  • 配置管理:不同环境(开发、测试、生产)的配置

与工厂方法的区别

特性工厂方法抽象工厂
创建对象单个对象对象族(多个相关对象)
工厂数量多个工厂(每个产品一个)多个工厂(每个产品族一个)
产品类型一种产品多种相关产品
扩展性新增产品容易新增产品族容易,新增产品类型困难
复杂度较简单较复杂

使用建议

  • 需要创建单个产品:使用工厂方法模式
  • 需要创建产品族:使用抽象工厂模式
  • 产品族固定,产品类型可能增加:考虑使用其他模式
  • 产品类型固定,产品族可能增加:使用抽象工厂模式

注意事项

⚠️ 抽象工厂模式虽然强大,但不要滥用:

  • 如果产品族很少(1-2个),可以考虑使用工厂方法模式
  • 如果产品类型很少(1-2个),可以考虑使用工厂方法模式
  • 抽象工厂模式会增加类的数量,要权衡利弊
  • 新增产品类型时,需要修改所有工厂类,违反开闭原则
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 18:48:42

Qwen3-Embedding-0.6B内存泄漏?资源监控与优化实战指南

Qwen3-Embedding-0.6B内存泄漏?资源监控与优化实战指南 在部署轻量级嵌入模型时,资源使用效率是开发者最关心的问题之一。Qwen3-Embedding-0.6B 作为 Qwen 家族中面向高效推理场景的文本嵌入模型,凭借其小体积、高精度和多语言支持能力&…

作者头像 李华
网站建设 2026/4/23 17:29:20

视频汇聚平台EasyCVR智慧水利工程全域可视化视频监控技术应用实践

在“数字中国”战略引领下,智慧水利建设已进入深水区,水资源调度、水灾害防御、水生态保护等核心业务对视频监控的依赖度持续攀升。传统的水利视频监控系统在设备兼容、数据融合与智能应用等方面面临严峻挑战。本文详细探讨了EasyCVR视频融合平台的智慧水…

作者头像 李华
网站建设 2026/4/18 10:05:28

dify生产集群性能翻倍秘诀,资深架构师绝不外传的优化技巧

第一章:dify生产环境高可用集群部署方案 在构建面向生产环境的dify平台时,高可用性与可扩展性是核心设计目标。通过集群化部署,结合负载均衡、服务发现与持久化存储机制,可有效避免单点故障,保障系统724小时稳定运行。…

作者头像 李华
网站建设 2026/4/18 7:50:06

FSMN-VAD安全优势:数据不出内网的合规部署方案

FSMN-VAD安全优势:数据不出内网的合规部署方案 1. FSMN-VAD 离线语音端点检测控制台 在语音识别、会议记录、智能客服等实际应用中,原始音频往往包含大量无效静音段,不仅浪费存储资源,也会影响后续处理效率。FSMN-VAD 是一种高效…

作者头像 李华
网站建设 2026/4/23 8:49:26

变量占位符这样用才正确,深度解读Dify提示词语法规范

第一章:变量占位符的核心概念与作用 变量占位符是编程语言中用于表示动态值的符号或语法结构,它允许开发者在字符串、模板或配置中预留位置,后续通过实际数据进行填充。这种机制广泛应用于日志输出、用户界面渲染、数据库查询和国际化支持等场…

作者头像 李华
网站建设 2026/5/2 4:57:37

FSMN VAD端口冲突怎么办?7860端口占用解决方法汇总

FSMN VAD端口冲突怎么办?7860端口占用解决方法汇总 1. FSMN VAD阿里开源的语音活动检测模型 构建by科哥 FSMN VAD是基于阿里达摩院FunASR项目开发的一款高精度语音活动检测(Voice Activity Detection, VAD)模型,能够精准识别音频…

作者头像 李华