工厂方法模式把创建延迟到子类简单工厂把所有产品的创建逻辑塞进一个工厂类新增产品必须修改工厂。工厂方法模式换了个思路不再用一个工厂创建所有产品而是为每种产品定义一个工厂让子类决定创建什么。这就是 GoF 23 种设计模式中的工厂方法模式。它比简单工厂更符合开闭原则代价是类的数量成倍增加。结构工厂方法模式包含四个角色抽象产品Product定义产品的接口具体产品Concrete Product实现产品接口的具体类抽象工厂Creator声明工厂方法返回抽象产品具体工厂Concrete Creator实现工厂方法返回具体产品抽象工厂中通常还包含一些依赖产品的业务逻辑这些逻辑调用工厂方法获取产品对象但不关心具体是哪个产品。代码实现还是用支付作为例子。抽象产品publicinterfacePayment{voidpay(doubleamount);}具体产品publicclassAliPayimplementsPayment{Overridepublicvoidpay(doubleamount){System.out.println(支付宝支付amount);}}publicclassWechatPayimplementsPayment{Overridepublicvoidpay(doubleamount){System.out.println(微信支付amount);}}抽象工厂publicabstractclassPaymentFactory{// 工厂方法由子类实现publicabstractPaymentcreatePayment();// 业务逻辑依赖工厂方法创建的产品publicvoidprocessPayment(doubleamount){PaymentpaymentcreatePayment();// 可以在这里加统一的处理逻辑比如日志、校验payment.pay(amount);}}具体工厂publicclassAliPayFactoryextendsPaymentFactory{OverridepublicPaymentcreatePayment(){returnnewAliPay();}}publicclassWechatPayFactoryextendsPaymentFactory{OverridepublicPaymentcreatePayment(){returnnewWechatPay();}}调用方publicclassClient{publicstaticvoidmain(String[]args){PaymentFactoryfactorynewAliPayFactory();factory.processPayment(100);}}调用方只依赖PaymentFactory抽象类和Payment接口完全不接触具体类。与简单工厂的关键区别简单工厂是一个工厂类创建所有产品工厂方法把创建延迟到子类每种产品对应一个工厂类。新增一种支付方式时简单工厂修改PaymentFactory的switch加一个case。工厂方法新增UnionPayFactory类不动任何已有代码。前者违反开闭原则后者符合。这是工厂方法最核心的优势。对比维度简单工厂工厂方法工厂类数量1 个N 个每个产品一个新增产品修改工厂类新增工厂类开闭原则违反符合代码复杂度低中适用场景产品少且稳定产品多且需扩展抽象工厂中的业务逻辑工厂方法不只是“返回一个对象”。抽象工厂里通常还有依赖产品的业务方法这些方法调用工厂方法获取产品再执行通用逻辑。publicabstractclassPaymentFactory{publicabstractPaymentcreatePayment();publicvoidprocessPayment(doubleamount){// 通用逻辑校验、日志、记录时间System.out.println(开始处理支付...);PaymentpaymentcreatePayment();payment.pay(amount);System.out.println(支付处理完成);}}子类只需要实现createPayment()通用的处理流程由抽象类统一定义。这是模板方法模式和工厂方法模式的经典组合——抽象类定义流程骨架子类填充具体产品的创建逻辑。何时用工厂方法产品种类会持续扩展。如果未来会不断增加新的产品类型工厂方法比简单工厂更合适因为扩展成本更低。需要把创建和使用分离到不同层次。框架设计常用工厂方法让框架定义抽象工厂具体产品由使用方通过子类提供。产品创建有复杂逻辑。每个产品可能有不同的初始化步骤放在各自的工厂类里更清晰。不希望调用方依赖具体产品类。调用方只认识抽象工厂和抽象产品具体类完全隐藏。何时不用产品种类少且稳定。如果只有两三种产品未来也不会增加简单工厂足够工厂方法反而增加了不必要的类。不需要扩展点。如果整个系统只有一处地方需要创建对象抽象出工厂类意义不大。类和接口已经很多了。工厂方法会让类数量翻倍如果项目本身结构复杂要谨慎权衡。在 Spring 中的体现Spring 的FactoryBean接口是工厂方法模式的一个变体publicinterfaceFactoryBeanT{TgetObject()throwsException;Class?getObjectType();booleanisSingleton();}getObject()就是工厂方法。你可以通过实现FactoryBean来定制复杂对象的创建过程Spring 容器在getBean()时会调用getObject()返回真正的对象。Spring 的BeanFactory体系本身也是工厂模式的集大成者。BeanFactory是抽象工厂XmlBeanFactory、AnnotationConfigApplicationContext等是具体工厂它们负责创建和管理 Bean。一个容易踩的坑抽象工厂里的工厂方法不要在构造方法或字段初始化时调用。因为子类构造方法执行时父类构造方法先执行此时子类的字段还没初始化createPayment()可能拿到不完整的对象。publicabstractclassPaymentFactory{privatePaymentdefaultPaymentcreatePayment();// ❌ 危险publicabstractPaymentcreatePayment();}正确做法是在业务方法中调用而不是在构造阶段。总结维度说明核心思想定义创建对象的接口让子类决定实例化哪个类角色抽象产品、具体产品、抽象工厂、具体工厂与简单工厂的区别每种产品一个工厂扩展时新增类而非修改已有代码优点符合开闭原则创建与使用分离职责清晰缺点类数量增加抽象层次提高典型组合与模板方法模式配合抽象类定义流程子类实现创建Spring 体现FactoryBean、BeanFactory体系工厂方法模式解决的是“新增产品要改工厂”的问题代价是多了一层继承体系。当产品种类会持续增长或者需要把创建逻辑下放到子类时它是比简单工厂更合适的选择。
企业数字化 ERP 产品动态
相关推荐
Atlas 300V 24G推理卡部署YOLO实战:从ONNX到OM模型转换 1. 先搞清楚:atlas到底是什么很多人第一次听到"atlas"这个名字,脑子里冒出来的是希腊神话里扛天的巨人,或者是波士顿动力那台跑来跑去的机器人。但在AI部署这个圈子里,atlas指的是华为昇腾生态下的整条AI计算产品线&… · 2026/9/26 16:17:20
【项目实战】深度指南:如何在 cc-switch 中配置 TaoToken 统一 API 通道 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 16:17:14
非接触式掌静脉识别毕设实战:从ROI提取到CNN模型训练全流程 简介:这份资源是面向高校计算机、人工智能及相关专业学生的非接触式掌静脉识别毕业设计完整方案,适合需要完成毕设、期末大作业或课程设计的人群,尤其对深度学习入门者友好。项目以Python实现,包含完整源码与配套论文,… · 2026/9/26 16:55:13
SpringBoot2+Vue3+MySQL8.0爱心商城系统全栈开发与部署指南 如果把 Java Web 项目分成“能跑”和“能给别人看”两档,爱心商城系统大概属于后者。这个项目用的是 SpringBoot2 Vue3 MyBatis-Plus MySQL8.0 这一套目前很主流的全栈组合,前后端分离,代码里带了完整的数据库脚本和部署文档,… · 2026/9/26 16:55:07
5G组网与运维赛项任务书解读:从工程交付到故障排查实战 1. 任务书到底在考什么:先看穿它的"工程交付"底色 2026年湖北省职业院校技能大赛5G组网与运维(高职学生组)任务书,估计已经让不少参赛队开始加练了。很多学生拿到任务书的第一件事,是把里面的命令背下来。我… · 2026/9/26 16:55:07
jsencrypt 前端 RSA 加密解密全攻略:密钥格式、uniapp 适配与避坑清单 简介:面向需要在前端项目或 uni-app 中实现 RSA 加密解密的前端开发者,该资源提供一套已适配 uni-app 的 jsencrypt 改造方案与封装调用示例。针对原生 jsencrypt 在 uni-app 中报错的问题,作者对库文件进行了调整,并额外提供 rsa… · 2026/9/26 16:55:07
Git 常用命令实战:从安装配置到分支管理、撤销回滚与远程协作 1. 安装与环境准备1.1 Git 安装方式小结Git 是当下开发者绕不开的工具,就算平时用 IDE 的图形按钮提交代码,底层的还是这一套命令。与其等出了问题对着错误提示干瞪眼,不如先把常用指令摸透。这篇文章没有废话,也不按什么“入门到… · 2026/9/26 16:55:07
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46