03-A-抽象工厂模式详解
03-A-抽象工厂模式详解关键词抽象工厂、产品族、配套对象、数据库方言、扩展性抽象工厂模式和工厂方法很像但关注点是一整套配套产品。比如你要换数据库不只是换一个连接池而是连接、分页、类型处理都要一起换。抽象工厂就是把这些配套产品的创建统一起来。 目录03-A-抽象工厂模式详解 术语速查表一、不用抽象工厂的问题二、模式结构三、业务场景多数据库方言支持四、与工厂方法的对比五、框架中的同款实现六、常见误用误用把工厂方法硬说成抽象工厂误用产品种类频繁变化七、总结 术语速查表术语人话解释产品族同一系列、配套使用的产品集合抽象工厂定义创建一系列产品的方法具体工厂创建某个产品族的工厂抽象产品某类产品的接口具体产品某个产品族里的具体实现一、不用抽象工厂的问题假设电商系统需要支持多种数据库MySQL 和 PostgreSQL。每种数据库都需要连接配置ConnectionConfig分页方言PaginationDialect类型转换器TypeConverter。不用抽象工厂代码可能这样写publicclassDbConfigFactory{publicObjectcreate(StringdbType,Stringname){if(mysql.equals(dbType)){if(connection.equals(name))returnnewMySQLConnectionConfig();if(pagination.equals(name))returnnewMySQLPaginationDialect();if(typeConverter.equals(name))returnnewMySQLTypeConverter();}elseif(postgres.equals(dbType)){// ...}thrownewIllegalArgumentException(unsupported);}}痛点不同数据库的配套对象散落在各处新增数据库类型要改很多地方类型转换是Object返回失去编译期检查。二、模式结构«abstract»DbFactorycreateConnectionConfig()createPaginationDialect()createTypeConverter()MySQLDbFactoryPostgresDbFactoryConnectionConfigPaginationDialectTypeConverter三、业务场景多数据库方言支持下面是整个业务场景的调用流程图Main 入口QueryExecutor 使用方DbFactory 抽象工厂MySQLDbFactory 具体工厂PostgresDbFactory 具体工厂MySQLConnectionConfigMySQLPaginationDialectMySQLTypeConverterPostgresConnectionConfigPostgresPaginationDialectPostgresTypeConverterdriver: com.mysql.cj.jdbc.DriverlimitSql: SELECT * FROM t_order LIMIT 0, 10type: BIGINTdriver: org.postgresql.DriverlimitSql: SELECT * FROM t_order LIMIT 10 OFFSET 0type: BIGINT下面把抽象产品、MySQL 产品族、PostgreSQL 产品族、抽象工厂与具体工厂、使用方整合到一个完整的 Java 文件中可直接编译运行。// 抽象产品interfaceConnectionConfig{StringgetDriverClass();StringgetUrlTemplate();}interfacePaginationDialect{StringbuildLimitSql(Stringsql,intoffset,intlimit);}interfaceTypeConverter{StringtoDbType(StringjavaType);}// MySQL 产品族classMySQLConnectionConfigimplementsConnectionConfig{OverridepublicStringgetDriverClass(){returncom.mysql.cj.jdbc.Driver;}OverridepublicStringgetUrlTemplate(){returnjdbc:mysql://${host}:${port}/${db};}}classMySQLPaginationDialectimplementsPaginationDialect{OverridepublicStringbuildLimitSql(Stringsql,intoffset,intlimit){returnsql LIMIT offset, limit;}}classMySQLTypeConverterimplementsTypeConverter{OverridepublicStringtoDbType(StringjavaType){returnBIGINT.equals(javaType)?BIGINT:VARCHAR;}}// PostgreSQL 产品族classPostgresConnectionConfigimplementsConnectionConfig{OverridepublicStringgetDriverClass(){returnorg.postgresql.Driver;}OverridepublicStringgetUrlTemplate(){returnjdbc:postgresql://${host}:${port}/${db};}}classPostgresPaginationDialectimplementsPaginationDialect{OverridepublicStringbuildLimitSql(Stringsql,intoffset,intlimit){returnsql LIMIT limit OFFSET offset;}}classPostgresTypeConverterimplementsTypeConverter{OverridepublicStringtoDbType(StringjavaType){returnBIGINT.equals(javaType)?BIGINT:TEXT;}}// 抽象工厂与具体工厂interfaceDbFactory{ConnectionConfigcreateConnectionConfig();PaginationDialectcreatePaginationDialect();TypeConvertercreateTypeConverter();}classMySQLDbFactoryimplementsDbFactory{OverridepublicConnectionConfigcreateConnectionConfig(){returnnewMySQLConnectionConfig();}OverridepublicPaginationDialectcreatePaginationDialect(){returnnewMySQLPaginationDialect();}OverridepublicTypeConvertercreateTypeConverter(){returnnewMySQLTypeConverter();}}classPostgresDbFactoryimplementsDbFactory{OverridepublicConnectionConfigcreateConnectionConfig(){returnnewPostgresConnectionConfig();}OverridepublicPaginationDialectcreatePaginationDialect(){returnnewPostgresPaginationDialect();}OverridepublicTypeConvertercreateTypeConverter(){returnnewPostgresTypeConverter();}}// 使用方classQueryExecutor{privatefinalDbFactoryfactory;publicQueryExecutor(DbFactoryfactory){this.factoryfactory;}publicvoidexecute(Stringsql,intoffset,intlimit){ConnectionConfigconnectionConfigfactory.createConnectionConfig();PaginationDialectdialectfactory.createPaginationDialect();TypeConverterconverterfactory.createTypeConverter();System.out.println(driver: connectionConfig.getDriverClass());System.out.println(limitSql: dialect.buildLimitSql(sql,offset,limit));System.out.println(type: converter.toDbType(Long));}}// 运行入口publicclassMain{publicstaticvoidmain(String[]args){System.out.println( MySQL );QueryExecutormysqlExecutornewQueryExecutor(newMySQLDbFactory());mysqlExecutor.execute(SELECT * FROM t_order,0,10);System.out.println();System.out.println( PostgreSQL );QueryExecutorpostgresExecutornewQueryExecutor(newPostgresDbFactory());postgresExecutor.execute(SELECT * FROM t_order,0,10);}}运行结果 MySQL driver: com.mysql.cj.jdbc.Driver limitSql: SELECT * FROM t_order LIMIT 0, 10 type: BIGINT PostgreSQL driver: org.postgresql.Driver limitSql: SELECT * FROM t_order LIMIT 10 OFFSET 0 type: BIGINT可以看到使用方QueryExecutor完全不感知具体数据库类型只依赖抽象的DbFactory。切换数据库时只需替换工厂实现配套产品连接、分页、类型转换会自动保持一致。从图中可以清晰看到Main只负责选择具体工厂QueryExecutor只依赖抽象的DbFactory而每个具体工厂负责创建自己产品族里的配套对象连接、分页、类型转换最终输出对应的方言结果。。四、与工厂方法的对比维度工厂方法抽象工厂粒度创建一个产品创建一族配套产品扩展新产品族容易容易新增一个具体工厂扩展新产品种类容易困难所有工厂接口都要改典型场景支付渠道数据库方言、UI 主题五、框架中的同款实现框架应用说明SpringApplicationContext创建 Bean不同环境dev/test/prod创建不同的 BeanJDBCConnection、Statement、ResultSet不同数据库驱动提供不同的实现MyBatisSqlSessionFactory 多数据库方言XML 解析出的对象由不同方言适配六、常见误用误用把工厂方法硬说成抽象工厂错误判断标准如果你只是根据类型创建不同对象那是工厂方法如果你创建的是一整套配套对象那才是抽象工厂。误用产品种类频繁变化如果每次需求都要在产品族里新增一种产品比如新增一个IndexDialect所有具体工厂都要改。这种情况下抽象工厂会变得很痛苦。七、总结抽象工厂的核心创建一族配套产品保证这些产品互相兼容。适用场景数据库方言、UI 主题、多环境配置。优点产品族切换方便使用方只依赖抽象。代价新增产品种类要改抽象工厂和所有具体工厂。与工厂方法的关系抽象工厂可以看成多个工厂方法的组合关注从一个产品升级到一族产品。上一篇02-A-工厂方法模式详解下一篇04-A-建造者模式详解

相关新闻

Vue路由缓存实战:keep-alive实现前进刷新返回不刷新

Vue路由缓存实战:keep-alive实现前进刷新返回不刷新

最近在某个后台管理项目里,我给一套多标签页框架折腾路由缓存,被一个问题卡了几个晚上:列表页里点开详情,返回列表时列表位置全丢了,而且每次返回列表页,created都会重新执行一遍,接口重打、loa…

2026/10/17 13:39:42 阅读更多 →
区块链应用操作员实战:从需求调研到部署运维的完整指南

区块链应用操作员实战:从需求调研到部署运维的完整指南

简介:面向区块链应用操作员考试与日常实操整理的PDF资料,系统涵盖基础知识、智能合约、链上操作、身份权限和隐私保护等核心模块,适合备考“区块链应用技术考试”的初学者与在职操作员对照学习。资源仅含1个PDF文件,压缩包大小708…

2026/10/17 13:39:42 阅读更多 →
Electron+Python语音工作台架构设计与跨平台实践

Electron+Python语音工作台架构设计与跨平台实践

1. 项目概述:一个跨平台语音工作台的诞生逻辑VoiceStudio 这个名字乍一听像某家音频硬件厂商的新品发布会,但实际它是一个用 Electron 构建、面向创作者与开发者的桌面级语音处理工作台。我第一次看到这个项目名是在 GitHub 上一个刚创建三天的仓库里&am…

2026/10/17 13:39:42 阅读更多 →

最新新闻

论文解读:语义感知后退视界规划器 面向物体中心的主动建图方案及工程参考

论文解读:语义感知后退视界规划器 面向物体中心的主动建图方案及工程参考

本文围绕2024年发表于IEEE Robotics and Automation Letters(RA-L)的论文《Semantics-Aware Receding Horizon Planner for Object-Centric Active Mapping》展开技术拆解,结合启元机器人的室内导航与场景建图需求,分析该方案的技…

2026/10/17 14:36:21 阅读更多 →
质子半导体剂量计基础

质子半导体剂量计基础

一、带电粒子与物质的四类相互作用 带电粒子(重带电粒子如质子、轻带电粒子如电子)入射物质,存在4种基础相互作用: 与核外电子的非弹性碰撞 库仑相互作用,粒子将能量传递给靶原子外层电子,造成原子电离或激发。这是带电粒子最主要的能量损失方式。LET(线性能量转移)统…

2026/10/17 14:36:21 阅读更多 →
artcraft创作工具链:从素材管理到输出归档的完整工作流

artcraft创作工具链:从素材管理到输出归档的完整工作流

1. 从“artcraft”这个名字说起:一个被低估的创作工具链思路第一次看到“artcraft”这个标题的时候,我脑子里蹦出来的第一反应是——这大概率不是一个单一工具,而是一整套围绕“创作”这件事搭建起来的工作流。为什么这么说?因为“…

2026/10/17 14:36:21 阅读更多 →
项目启动与系统设计阶段总结:从需求调研到技术落地的关键实践

项目启动与系统设计阶段总结:从需求调研到技术落地的关键实践

这篇不是我写的,是别人文章。你想让我扮演那个“全能型资深博主”,根据标题生成一篇符合规范的长文。我来写。 “项目启动与系统设计阶段总结”,这个标题我太熟了。每隔一两个季度,我们组里就会写一篇类似的东西,挂在…

2026/10/17 14:36:21 阅读更多 →
ArtCraft:参数化材质生成方法论与可复用创意工作流

ArtCraft:参数化材质生成方法论与可复用创意工作流

1. 项目概述:ArtCraft 不是“艺术手作”的简单拼贴,而是一套可落地的创意生产方法论ArtCraft 这个词乍看像英文直译——art(艺术)和 craft(工艺/手艺)的组合,很容易被理解成“艺术手工”“创意D…

2026/10/17 14:36:21 阅读更多 →
Qt串口电源控制工具:一键开关设备电源

Qt串口电源控制工具:一键开关设备电源

简介:这是一份基于Qt框架开发的RS232串口电源控制程序,面向嵌入式初学者、电子工程实践者及自动化设备控制开发者,解决实验室/测试场景中对程控电源的远程开关与状态交互需求。项目采用C与Qt构建跨平台GUI应用,通过串口发送指令实…

2026/10/17 14:35:20 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →