Java 23 种设计模式从踩坑到精通 | 工厂模式 —— 还在写一坨 if-else简单工厂→工厂方法→抽象工厂全演进摘要还在用一坨 if-else 创建对象本文带你走完简单工厂→工厂方法→抽象工厂的完整演进路线附 JDK、Spring、MyBatis 源码案例彻底搞懂三种工厂的区别与选型。《Java 23 种设计模式从踩坑到精通》开篇系列介绍与目录 上一篇单例模式 当前工厂模式 下一篇抽象工厂模式 返回系列总目录1. 从一段“if-else”屎山说起看看下面这段代码你是不是也曾在项目里这样写过if(type.equals(sms)){sendernewSmsSender();}elseif(type.equals(email)){sendernewEmailSender();}elseif(type.equals(wechat)){sendernewWechatSender();}这段代码看似简单却藏着三个致命问题紧耦合客户端代码直接依赖SmsSender、EmailSender等具体类一旦类名或构造函数变化所有调用方都要改。违反 OCP每加一种渠道就要修改if-else而修改现有代码可能引入新的 Bug。单元测试困难无法注入 Mock 对象测试时必须真实创建所有依赖。工厂模式的核心使命就是把对象的创建和使用分离让变化集中在 Factory调用方只依赖抽象接口。2. 模式家族的三种形态工厂模式不是单一模式而是一个“三兄弟”家族对比维度简单工厂工厂方法抽象工厂类图复杂度★★★★★★核心思想一个工厂根据参数创建不同产品让子类决定实例化哪个产品创建一系列相关产品族产品数量多种产品共用一个工厂每个产品对应一个工厂一个工厂生产一族产品开闭原则违反符合符合产品族维度2.1 一分钟选型指南你的场景推荐模式一句话理由产品种类少≤3种且基本不变简单工厂够用就好过度设计无益产品种类多、频繁新增工厂方法新增产品只需新加工厂类符合开闭原则产品成族出现、需整体切换抽象工厂如支付渠道、跨平台UI保证产品族一致提示简单工厂并不在 GoF 23 种设计模式之列但它是最常用的编程习惯也是理解工厂方法的基础。3. 简单工厂模式 —— 把 if-else 搬个家3.1 UML 类图三个角色抽象产品Product定义产品的公共接口具体产品ConcreteProduct实现抽象产品接口工厂类Factory根据参数判断返回对应的具体产品实例。3.2 代码实现消息发送器① 抽象产品publicinterfaceSender{voidsend(Stringmessage);}② 具体产品publicclassSmsSenderimplementsSender{Overridepublicvoidsend(Stringmessage){System.out.println(【短信】发送message);}}publicclassEmailSenderimplementsSender{Overridepublicvoidsend(Stringmessage){System.out.println(【邮件】发送message);}}③ 简单工厂publicclassSenderFactory{publicstaticSendercreate(Stringtype){switch(type){casesms:returnnewSmsSender();caseemail:returnnewEmailSender();default:thrownewIllegalArgumentException(未知渠道类型type);}}}⚠️ 简单工厂只是把if-else搬了家新增产品仍需修改工厂类违反开闭原则。④ 客户端调用SendersenderSenderFactory.create(sms);sender.send(你好工厂模式);3.3 优缺点优点缺点客户端与具体产品解耦职责清晰违反开闭原则新增产品必须修改switch逻辑创建逻辑集中管理调用简单工厂类职责过重所有产品的创建压力集中在一个类中适合产品种类少、变化不频繁的场景使用静态方法工厂类无法形成基于继承的等级结构⚠️核心矛盾简单工厂只是把if-else从业务代码搬到了工厂类本质上没有消除switch。当产品种类持续增长时工厂类会变成“超级工厂”。4. 工厂方法模式 —— 把变化隔离到子类4.1 核心思想简单工厂用一个类扛所有创建逻辑工厂方法模式则把“创建”这个动作抽象成接口让每个具体产品都有一个对应的具体工厂来创建。一句话理解简单工厂是“我去找工厂要产品”工厂方法是“我去找具体的工厂子类要它擅长的产品”。4.2 UML 类图四个角色抽象工厂Factory声明创建产品的工厂方法返回抽象产品类型具体工厂ConcreteFactory实现工厂方法返回一个具体产品实例抽象产品Product定义产品的公共接口具体产品ConcreteProduct实现抽象产品接口。4.3 代码实现① 抽象工厂接口publicinterfaceSenderFactory{SendercreateSender();}② 具体工厂类publicclassSmsSenderFactoryimplementsSenderFactory{OverridepublicSendercreateSender(){returnnewSmsSender();}}publicclassEmailSenderFactoryimplementsSenderFactory{OverridepublicSendercreateSender(){returnnewEmailSender();}}✅ 新增产品只需新加工厂子类完全符合开闭原则但每种产品都要对应一个工厂类类数量会膨胀。③ 客户端调用SenderFactoryfactorynewSmsSenderFactory();Sendersenderfactory.createSender();sender.send(你好工厂方法);4.4 优缺点优点缺点完全符合开闭原则新增产品只需新增一个工厂子类零修改现有代码类的数量会急剧膨胀每个产品都要配一个工厂类每个工厂职责单一逻辑清晰系统复杂度增加适合产品种类较多的场景支持基于继承的工厂等级结构客户端需要知道具体工厂类的名字5. 抽象工厂模式 —— 产品族一键创建5.1 核心思想工厂方法解决的是单一产品的创建问题但现实开发中我们常常需要同时创建一系列相互关联的产品称为“产品族”。例如一个跨平台 UI 组件库需要同时创建按钮、文本框且必须保证它们风格统一全 Win 风格或全 Mac 风格。抽象工厂模式正是为此而生提供一个创建一系列相关或相互依赖对象的接口而无需指定它们具体的类。5.2 两个关键概念产品等级结构即产品的继承结构例如按钮是一个抽象类Windows 按钮和 Mac 按钮是其具体子类。产品族由同一个工厂生产的、位于不同产品等级结构中的一组产品。例如 Windows 工厂生产的 Windows 按钮 Windows 文本框构成一个产品族。5.3 UML 类图四个角色抽象工厂AbstractFactory声明一组创建产品族的方法具体工厂ConcreteFactory实现抽象工厂生成一个产品族的所有产品抽象产品AbstractProduct为每种产品声明接口具体产品ConcreteProduct定义具体工厂生产的具体产品对象。5.4 代码实现跨平台 UI 组件① 抽象产品publicinterfaceButton{voidpaint();}publicinterfaceTextField{voidrender();}② 具体产品Windows 风格publicclassWinButtonimplementsButton{Overridepublicvoidpaint(){System.out.println(Windows 风格按钮);}}publicclassWinTextFieldimplementsTextField{Overridepublicvoidrender(){System.out.println(Windows 风格文本框);}}③ 具体产品Mac 风格publicclassMacButtonimplementsButton{Overridepublicvoidpaint(){System.out.println(Mac 风格按钮);}}publicclassMacTextFieldimplementsTextField{Overridepublicvoidrender(){System.out.println(Mac 风格文本框);}}④ 抽象工厂publicinterfaceGUIFactory{ButtoncreateButton();TextFieldcreateTextField();}⑤ 具体工厂publicclassWinFactoryimplementsGUIFactory{OverridepublicButtoncreateButton(){returnnewWinButton();}OverridepublicTextFieldcreateTextField(){returnnewWinTextField();}}publicclassMacFactoryimplementsGUIFactory{OverridepublicButtoncreateButton(){returnnewMacButton();}OverridepublicTextFieldcreateTextField(){returnnewMacTextField();}}✅ 保证产品族一致性切换工厂即可整体换肤⚠️ 新增产品类型如新增Checkbox需要修改所有工厂类。⑥ 客户端调用GUIFactoryfactorynewWinFactory();// 只需切换这一行Buttonbuttonfactory.createButton();TextFieldtextFieldfactory.createTextField();button.paint();// Windows 风格按钮textField.render();// Windows 风格文本框5.5 优缺点优点缺点保证产品族兼容性所有产品来自同一工厂风格/协议一致新增产品等级困难如果要新增一个 Checkbox 产品抽象工厂和所有具体工厂都要修改客户端代码与具体平台/产品族解耦类的数量进一步膨胀系统更加复杂切换产品族只需替换工厂实例仅适用于存在产品族且产品等级相对稳定的场景6. 工厂模式进化三步走回顾三种模式的演进你会发现它们解决的问题层层递进选型指南场景推荐模式判断依据产品种类少≤3 种且基本不变简单工厂代码最简单过度设计无益产品种类多、频繁新增工厂方法新增产品只需新增工厂类符合 OCP产品成族出现、需整体切换抽象工厂如 UI 主题、数据库驱动、支付渠道家族黄金法则能用简单工厂就别上工厂方法能用工厂方法就别上抽象工厂。模式是为解决问题服务的不是为了炫技。正在追更《Java 23 种设计模式从踩坑到精通》点击右上角「关注」不错过下一篇——抽象工厂产品族创建如何避免“一锅粥”7. 框架中的工厂模式7.1 JDKCalendar.getInstance() —— 简单工厂JDK 中的java.util.Calendar类是简单工厂模式的经典应用。// JDK 源码简化示意publicabstractclassCalendar{publicstaticCalendargetInstance(){returncreateCalendar(TimeZone.getDefault(),Locale.getDefault());}privatestaticCalendarcreateCalendar(TimeZonezone,Localelocale){// 根据地区和语言返回不同的 Calendar 子类实例if(th.equals(locale.getLanguage())TH.equals(locale.getCountry())){returnnewBuddhistCalendar(zone,locale);}returnnewGregorianCalendar(zone,locale);}}调用方只需Calendar.getInstance()无需知道背后到底是GregorianCalendar还是BuddhistCalendar。7.2 Spring IoC 容器 —— 工厂方法 抽象工厂Spring 的BeanFactory是工厂方法模式的经典实现。// BeanFactory 是抽象工厂声明了获取 Bean 的接口publicinterfaceBeanFactory{ObjectgetBean(Stringname);TTgetBean(ClassTrequiredType);// ...}而FactoryBeanT则是工厂方法的进一步封装——它本身是一个 Bean但其getObject()方法负责创建并返回另一个复杂对象。BeanFactory是管理所有 Bean 的容器本身抽象工厂而FactoryBean是容器中用于生产特定复杂对象的特殊 Bean工厂方法。二者一纵一横共同构成了 Spring 强大的对象创建体系。7.3 MyBatisSqlSessionFactory —— 抽象工厂MyBatis 的SqlSessionFactory负责创建SqlSession实例涉及数据库连接、事务管理等复杂配置是典型的抽象工厂模式publicinterfaceSqlSessionFactory{SqlSessionopenSession();// ...}8. 常见误区与面试高频题❌ 误区1简单工厂就是工厂方法简单工厂不属于 GoF 23 种设计模式它使用静态方法且只有一个工厂类工厂方法则通过抽象工厂接口 多个具体工厂子类实现多态创建。❌ 误区2工厂方法可以替代简单工厂如果产品种类很少且变化不大简单工厂足够用了。强行上工厂方法只会导致类数量膨胀得不偿失。❌ 误区3抽象工厂比工厂方法“高级”它们是解决不同问题的工具不存在高低之分。如果产品之间不构成“产品族”抽象工厂反而是过度设计。 面试高频追问简单工厂违背了什么原则→ 开闭原则OCP新增产品需修改工厂类中的switch逻辑。工厂方法和抽象工厂的本质区别是什么→ 工厂方法解决单一产品的横向扩展抽象工厂解决产品族的纵向创建。BeanFactory和FactoryBean分别是什么模式→BeanFactory是抽象工厂模式FactoryBean是工厂方法模式。9. 六大设计原则在工厂模式中的体现设计原则在工厂模式中的体现单一职责原则SRP每个具体工厂只负责创建一种产品职责内聚开闭原则OCP工厂方法新增产品只需加新工厂类无需修改现有代码里氏替换原则LSP客户端使用抽象产品类型具体产品可任意替换依赖倒置原则DIP客户端依赖抽象工厂和抽象产品接口而非具体实现类接口隔离原则ISP抽象工厂按产品族维度拆分接口避免“胖接口”迪米特法则LoD客户端只需知道工厂和产品接口无需了解内部创建细节10. 总结对比一览对比维度简单工厂工厂方法抽象工厂GoF 收录否是是工厂数量1 个N 个每产品一工厂N 个每产品族一工厂产品数量多种一种每工厂一族多产品开闭原则违反符合部分符合类复杂度★☆☆☆★★★☆★★★★推荐指数★★★☆★★★★★★★★★典型应用Calendar.getInstance()SpringFactoryBeanMyBatisSqlSessionFactory✅建议日常开发中优先考虑简单工厂够用即止产品种类多且频繁扩展时升级为工厂方法系统存在产品族概念时如多端 UI、多数据库果断使用抽象工厂。附录| Factory UML 源码Simple Factory UML 源码startuml skinparam backgroundColor #FEFEFE interface Product { operation() } class ConcreteProductA implements Product class ConcreteProductB implements Product class SimpleFactory { createProduct(type) : Product } SimpleFactory .. Product : creates endumlSenderFactory UML 源码startuml skinparam backgroundColor #FEFEFE skinparam classBorderColor #333333 skinparam classFontColor #333333 skinparam arrowColor #555555 skinparam classBackgroundColor #F9F9F9 interface SenderFactory { createSender(): Sender } class SmsSenderFactory implements SenderFactory { createSender(): Sender } class EmailSenderFactory implements SenderFactory { createSender(): Sender } interface Sender { send(message: String): void } class SmsSender implements Sender { send(message: String): void } class EmailSender implements Sender { send(message: String): void } SmsSenderFactory .. SmsSender : creates EmailSenderFactory .. EmailSender : creates endumlGUIFactory UML 源码startuml skinparam backgroundColor #FEFEFE skinparam classBorderColor #333333 skinparam classFontColor #333333 skinparam arrowColor #555555 skinparam classBackgroundColor #F9F9F9 interface GUIFactory { createButton(): Button createTextField(): TextField } class WinFactory implements GUIFactory { createButton(): Button createTextField(): TextField } class MacFactory implements GUIFactory { createButton(): Button createTextField(): TextField } interface Button { paint(): void } interface TextField { render(): void } class WinButton implements Button { paint(): void } class MacButton implements Button { paint(): void } class WinTextField implements TextField { render(): void } class MacTextField implements TextField { render(): void } WinFactory .. WinButton : creates WinFactory .. WinTextField : creates MacFactory .. MacButton : creates MacFactory .. MacTextField : creates enduml 《Java 23 种设计模式从踩坑到精通》快速导航开篇系列介绍与目录上一篇单例模式当前工厂模式你在这里下一篇抽象工厂模式创建型模式汇总单例、工厂、建造者、原型结构型模式汇总适配器、装饰器、代理……行为型模式汇总观察者、策略、模板方法…… 关注《Java 23 种设计模式从踩坑到精通》用 25 篇文章彻底吃透设计模式让代码设计成为你的本能。福利预告全系列代码及 UML 源码将在完结时统一打包开放点击「关注」「收藏」第一时间获取。下一篇抽象工厂模式——支付渠道 收款渠道如何保证成套创建跨平台 UI 如何一键换肤 除了设计模式我也在深挖智能物流实战出版社WMS、托盘调度、机器学习落地。如果你对技术在不同领域的实战感兴趣欢迎点击我的头像看看专栏《出版社物流WMS智能调度实战》。技术相通思路可鉴。
Java 23 种设计模式:从踩坑到精通 | 工厂模式 —— 还在写一坨 if-else?简单工厂→工厂方法→抽象工厂全演进
Java 23 种设计模式从踩坑到精通 | 工厂模式 —— 还在写一坨 if-else简单工厂→工厂方法→抽象工厂全演进摘要还在用一坨 if-else 创建对象本文带你走完简单工厂→工厂方法→抽象工厂的完整演进路线附 JDK、Spring、MyBatis 源码案例彻底搞懂三种工厂的区别与选型。《Java 23 种设计模式从踩坑到精通》开篇系列介绍与目录 上一篇单例模式 当前工厂模式 下一篇抽象工厂模式 返回系列总目录1. 从一段“if-else”屎山说起看看下面这段代码你是不是也曾在项目里这样写过if(type.equals(sms)){sendernewSmsSender();}elseif(type.equals(email)){sendernewEmailSender();}elseif(type.equals(wechat)){sendernewWechatSender();}这段代码看似简单却藏着三个致命问题紧耦合客户端代码直接依赖SmsSender、EmailSender等具体类一旦类名或构造函数变化所有调用方都要改。违反 OCP每加一种渠道就要修改if-else而修改现有代码可能引入新的 Bug。单元测试困难无法注入 Mock 对象测试时必须真实创建所有依赖。工厂模式的核心使命就是把对象的创建和使用分离让变化集中在 Factory调用方只依赖抽象接口。2. 模式家族的三种形态工厂模式不是单一模式而是一个“三兄弟”家族对比维度简单工厂工厂方法抽象工厂类图复杂度★★★★★★核心思想一个工厂根据参数创建不同产品让子类决定实例化哪个产品创建一系列相关产品族产品数量多种产品共用一个工厂每个产品对应一个工厂一个工厂生产一族产品开闭原则违反符合符合产品族维度2.1 一分钟选型指南你的场景推荐模式一句话理由产品种类少≤3种且基本不变简单工厂够用就好过度设计无益产品种类多、频繁新增工厂方法新增产品只需新加工厂类符合开闭原则产品成族出现、需整体切换抽象工厂如支付渠道、跨平台UI保证产品族一致提示简单工厂并不在 GoF 23 种设计模式之列但它是最常用的编程习惯也是理解工厂方法的基础。3. 简单工厂模式 —— 把 if-else 搬个家3.1 UML 类图三个角色抽象产品Product定义产品的公共接口具体产品ConcreteProduct实现抽象产品接口工厂类Factory根据参数判断返回对应的具体产品实例。3.2 代码实现消息发送器① 抽象产品publicinterfaceSender{voidsend(Stringmessage);}② 具体产品publicclassSmsSenderimplementsSender{Overridepublicvoidsend(Stringmessage){System.out.println(【短信】发送message);}}publicclassEmailSenderimplementsSender{Overridepublicvoidsend(Stringmessage){System.out.println(【邮件】发送message);}}③ 简单工厂publicclassSenderFactory{publicstaticSendercreate(Stringtype){switch(type){casesms:returnnewSmsSender();caseemail:returnnewEmailSender();default:thrownewIllegalArgumentException(未知渠道类型type);}}}⚠️ 简单工厂只是把if-else搬了家新增产品仍需修改工厂类违反开闭原则。④ 客户端调用SendersenderSenderFactory.create(sms);sender.send(你好工厂模式);3.3 优缺点优点缺点客户端与具体产品解耦职责清晰违反开闭原则新增产品必须修改switch逻辑创建逻辑集中管理调用简单工厂类职责过重所有产品的创建压力集中在一个类中适合产品种类少、变化不频繁的场景使用静态方法工厂类无法形成基于继承的等级结构⚠️核心矛盾简单工厂只是把if-else从业务代码搬到了工厂类本质上没有消除switch。当产品种类持续增长时工厂类会变成“超级工厂”。4. 工厂方法模式 —— 把变化隔离到子类4.1 核心思想简单工厂用一个类扛所有创建逻辑工厂方法模式则把“创建”这个动作抽象成接口让每个具体产品都有一个对应的具体工厂来创建。一句话理解简单工厂是“我去找工厂要产品”工厂方法是“我去找具体的工厂子类要它擅长的产品”。4.2 UML 类图四个角色抽象工厂Factory声明创建产品的工厂方法返回抽象产品类型具体工厂ConcreteFactory实现工厂方法返回一个具体产品实例抽象产品Product定义产品的公共接口具体产品ConcreteProduct实现抽象产品接口。4.3 代码实现① 抽象工厂接口publicinterfaceSenderFactory{SendercreateSender();}② 具体工厂类publicclassSmsSenderFactoryimplementsSenderFactory{OverridepublicSendercreateSender(){returnnewSmsSender();}}publicclassEmailSenderFactoryimplementsSenderFactory{OverridepublicSendercreateSender(){returnnewEmailSender();}}✅ 新增产品只需新加工厂子类完全符合开闭原则但每种产品都要对应一个工厂类类数量会膨胀。③ 客户端调用SenderFactoryfactorynewSmsSenderFactory();Sendersenderfactory.createSender();sender.send(你好工厂方法);4.4 优缺点优点缺点完全符合开闭原则新增产品只需新增一个工厂子类零修改现有代码类的数量会急剧膨胀每个产品都要配一个工厂类每个工厂职责单一逻辑清晰系统复杂度增加适合产品种类较多的场景支持基于继承的工厂等级结构客户端需要知道具体工厂类的名字5. 抽象工厂模式 —— 产品族一键创建5.1 核心思想工厂方法解决的是单一产品的创建问题但现实开发中我们常常需要同时创建一系列相互关联的产品称为“产品族”。例如一个跨平台 UI 组件库需要同时创建按钮、文本框且必须保证它们风格统一全 Win 风格或全 Mac 风格。抽象工厂模式正是为此而生提供一个创建一系列相关或相互依赖对象的接口而无需指定它们具体的类。5.2 两个关键概念产品等级结构即产品的继承结构例如按钮是一个抽象类Windows 按钮和 Mac 按钮是其具体子类。产品族由同一个工厂生产的、位于不同产品等级结构中的一组产品。例如 Windows 工厂生产的 Windows 按钮 Windows 文本框构成一个产品族。5.3 UML 类图四个角色抽象工厂AbstractFactory声明一组创建产品族的方法具体工厂ConcreteFactory实现抽象工厂生成一个产品族的所有产品抽象产品AbstractProduct为每种产品声明接口具体产品ConcreteProduct定义具体工厂生产的具体产品对象。5.4 代码实现跨平台 UI 组件① 抽象产品publicinterfaceButton{voidpaint();}publicinterfaceTextField{voidrender();}② 具体产品Windows 风格publicclassWinButtonimplementsButton{Overridepublicvoidpaint(){System.out.println(Windows 风格按钮);}}publicclassWinTextFieldimplementsTextField{Overridepublicvoidrender(){System.out.println(Windows 风格文本框);}}③ 具体产品Mac 风格publicclassMacButtonimplementsButton{Overridepublicvoidpaint(){System.out.println(Mac 风格按钮);}}publicclassMacTextFieldimplementsTextField{Overridepublicvoidrender(){System.out.println(Mac 风格文本框);}}④ 抽象工厂publicinterfaceGUIFactory{ButtoncreateButton();TextFieldcreateTextField();}⑤ 具体工厂publicclassWinFactoryimplementsGUIFactory{OverridepublicButtoncreateButton(){returnnewWinButton();}OverridepublicTextFieldcreateTextField(){returnnewWinTextField();}}publicclassMacFactoryimplementsGUIFactory{OverridepublicButtoncreateButton(){returnnewMacButton();}OverridepublicTextFieldcreateTextField(){returnnewMacTextField();}}✅ 保证产品族一致性切换工厂即可整体换肤⚠️ 新增产品类型如新增Checkbox需要修改所有工厂类。⑥ 客户端调用GUIFactoryfactorynewWinFactory();// 只需切换这一行Buttonbuttonfactory.createButton();TextFieldtextFieldfactory.createTextField();button.paint();// Windows 风格按钮textField.render();// Windows 风格文本框5.5 优缺点优点缺点保证产品族兼容性所有产品来自同一工厂风格/协议一致新增产品等级困难如果要新增一个 Checkbox 产品抽象工厂和所有具体工厂都要修改客户端代码与具体平台/产品族解耦类的数量进一步膨胀系统更加复杂切换产品族只需替换工厂实例仅适用于存在产品族且产品等级相对稳定的场景6. 工厂模式进化三步走回顾三种模式的演进你会发现它们解决的问题层层递进选型指南场景推荐模式判断依据产品种类少≤3 种且基本不变简单工厂代码最简单过度设计无益产品种类多、频繁新增工厂方法新增产品只需新增工厂类符合 OCP产品成族出现、需整体切换抽象工厂如 UI 主题、数据库驱动、支付渠道家族黄金法则能用简单工厂就别上工厂方法能用工厂方法就别上抽象工厂。模式是为解决问题服务的不是为了炫技。正在追更《Java 23 种设计模式从踩坑到精通》点击右上角「关注」不错过下一篇——抽象工厂产品族创建如何避免“一锅粥”7. 框架中的工厂模式7.1 JDKCalendar.getInstance() —— 简单工厂JDK 中的java.util.Calendar类是简单工厂模式的经典应用。// JDK 源码简化示意publicabstractclassCalendar{publicstaticCalendargetInstance(){returncreateCalendar(TimeZone.getDefault(),Locale.getDefault());}privatestaticCalendarcreateCalendar(TimeZonezone,Localelocale){// 根据地区和语言返回不同的 Calendar 子类实例if(th.equals(locale.getLanguage())TH.equals(locale.getCountry())){returnnewBuddhistCalendar(zone,locale);}returnnewGregorianCalendar(zone,locale);}}调用方只需Calendar.getInstance()无需知道背后到底是GregorianCalendar还是BuddhistCalendar。7.2 Spring IoC 容器 —— 工厂方法 抽象工厂Spring 的BeanFactory是工厂方法模式的经典实现。// BeanFactory 是抽象工厂声明了获取 Bean 的接口publicinterfaceBeanFactory{ObjectgetBean(Stringname);TTgetBean(ClassTrequiredType);// ...}而FactoryBeanT则是工厂方法的进一步封装——它本身是一个 Bean但其getObject()方法负责创建并返回另一个复杂对象。BeanFactory是管理所有 Bean 的容器本身抽象工厂而FactoryBean是容器中用于生产特定复杂对象的特殊 Bean工厂方法。二者一纵一横共同构成了 Spring 强大的对象创建体系。7.3 MyBatisSqlSessionFactory —— 抽象工厂MyBatis 的SqlSessionFactory负责创建SqlSession实例涉及数据库连接、事务管理等复杂配置是典型的抽象工厂模式publicinterfaceSqlSessionFactory{SqlSessionopenSession();// ...}8. 常见误区与面试高频题❌ 误区1简单工厂就是工厂方法简单工厂不属于 GoF 23 种设计模式它使用静态方法且只有一个工厂类工厂方法则通过抽象工厂接口 多个具体工厂子类实现多态创建。❌ 误区2工厂方法可以替代简单工厂如果产品种类很少且变化不大简单工厂足够用了。强行上工厂方法只会导致类数量膨胀得不偿失。❌ 误区3抽象工厂比工厂方法“高级”它们是解决不同问题的工具不存在高低之分。如果产品之间不构成“产品族”抽象工厂反而是过度设计。 面试高频追问简单工厂违背了什么原则→ 开闭原则OCP新增产品需修改工厂类中的switch逻辑。工厂方法和抽象工厂的本质区别是什么→ 工厂方法解决单一产品的横向扩展抽象工厂解决产品族的纵向创建。BeanFactory和FactoryBean分别是什么模式→BeanFactory是抽象工厂模式FactoryBean是工厂方法模式。9. 六大设计原则在工厂模式中的体现设计原则在工厂模式中的体现单一职责原则SRP每个具体工厂只负责创建一种产品职责内聚开闭原则OCP工厂方法新增产品只需加新工厂类无需修改现有代码里氏替换原则LSP客户端使用抽象产品类型具体产品可任意替换依赖倒置原则DIP客户端依赖抽象工厂和抽象产品接口而非具体实现类接口隔离原则ISP抽象工厂按产品族维度拆分接口避免“胖接口”迪米特法则LoD客户端只需知道工厂和产品接口无需了解内部创建细节10. 总结对比一览对比维度简单工厂工厂方法抽象工厂GoF 收录否是是工厂数量1 个N 个每产品一工厂N 个每产品族一工厂产品数量多种一种每工厂一族多产品开闭原则违反符合部分符合类复杂度★☆☆☆★★★☆★★★★推荐指数★★★☆★★★★★★★★★典型应用Calendar.getInstance()SpringFactoryBeanMyBatisSqlSessionFactory✅建议日常开发中优先考虑简单工厂够用即止产品种类多且频繁扩展时升级为工厂方法系统存在产品族概念时如多端 UI、多数据库果断使用抽象工厂。附录| Factory UML 源码Simple Factory UML 源码startuml skinparam backgroundColor #FEFEFE interface Product { operation() } class ConcreteProductA implements Product class ConcreteProductB implements Product class SimpleFactory { createProduct(type) : Product } SimpleFactory .. Product : creates endumlSenderFactory UML 源码startuml skinparam backgroundColor #FEFEFE skinparam classBorderColor #333333 skinparam classFontColor #333333 skinparam arrowColor #555555 skinparam classBackgroundColor #F9F9F9 interface SenderFactory { createSender(): Sender } class SmsSenderFactory implements SenderFactory { createSender(): Sender } class EmailSenderFactory implements SenderFactory { createSender(): Sender } interface Sender { send(message: String): void } class SmsSender implements Sender { send(message: String): void } class EmailSender implements Sender { send(message: String): void } SmsSenderFactory .. SmsSender : creates EmailSenderFactory .. EmailSender : creates endumlGUIFactory UML 源码startuml skinparam backgroundColor #FEFEFE skinparam classBorderColor #333333 skinparam classFontColor #333333 skinparam arrowColor #555555 skinparam classBackgroundColor #F9F9F9 interface GUIFactory { createButton(): Button createTextField(): TextField } class WinFactory implements GUIFactory { createButton(): Button createTextField(): TextField } class MacFactory implements GUIFactory { createButton(): Button createTextField(): TextField } interface Button { paint(): void } interface TextField { render(): void } class WinButton implements Button { paint(): void } class MacButton implements Button { paint(): void } class WinTextField implements TextField { render(): void } class MacTextField implements TextField { render(): void } WinFactory .. WinButton : creates WinFactory .. WinTextField : creates MacFactory .. MacButton : creates MacFactory .. MacTextField : creates enduml 《Java 23 种设计模式从踩坑到精通》快速导航开篇系列介绍与目录上一篇单例模式当前工厂模式你在这里下一篇抽象工厂模式创建型模式汇总单例、工厂、建造者、原型结构型模式汇总适配器、装饰器、代理……行为型模式汇总观察者、策略、模板方法…… 关注《Java 23 种设计模式从踩坑到精通》用 25 篇文章彻底吃透设计模式让代码设计成为你的本能。福利预告全系列代码及 UML 源码将在完结时统一打包开放点击「关注」「收藏」第一时间获取。下一篇抽象工厂模式——支付渠道 收款渠道如何保证成套创建跨平台 UI 如何一键换肤 除了设计模式我也在深挖智能物流实战出版社WMS、托盘调度、机器学习落地。如果你对技术在不同领域的实战感兴趣欢迎点击我的头像看看专栏《出版社物流WMS智能调度实战》。技术相通思路可鉴。