news 2026/4/28 5:00:28

【Java EE】工厂模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Java EE】工厂模式

工厂模式

  • 🍔 为什么需要工厂模式?
  • 简单工厂模式
    • 💡 核心思想
    • 🛠️ 代码实现
    • 📊 优缺点分析
  • 工厂方法模式
    • 💡 核心思想
    • 🛠️ 代码实现
    • 📊 优缺点分析
  • 抽象工厂模式
    • 💡 核心思想
    • 🛠️ 代码实现
    • 📊 优缺点分析
  • 🧠 总结与对比

🍔 为什么需要工厂模式?

假设你开了一家咖啡店,代码是这样写的:

publicclassCoffeeStore{publicCoffeeorderCoffee(Stringtype){Coffeecoffee=null;if("americano".equals(type)){coffee=newAmericano();}elseif("latte".equals(type)){coffee=newLatte();}// 加糖加奶...returncoffee;}}

问题来了:如果现在要加一种卡布奇诺,必须修改orderCoffee方法的源码,这违反了开闭原则(对扩展开放,对修改关闭)。而且,咖啡店不仅负责卖咖啡,还负责生产咖啡,职责不单一。
这时候,我们把生产咖啡的活儿剥离出去,交给专门的工厂来做。

简单工厂模式

简单工厂其实不属于 GoF 23 种设计模式,但它太常用了,可以说是工厂模式的入门。

💡 核心思想

定义一个工厂类,根据传入的参数不同,返回不同的对象实例。

🛠️ 代码实现

// 1. 定义咖啡接口publicinterfaceCoffee{voidmake();}// 2. 具体咖啡实现publicclassAmericanoimplementsCoffee{@Overridepublicvoidmake(){System.out.println("制作美式咖啡...");}}publicclassLatteimplementsCoffee{@Overridepublicvoidmake(){System.out.println("制作拿铁咖啡...");}}// 3. 简单工厂类 (核心)publicclassSimpleCoffeeFactory{publicstaticCoffeecreateCoffee(Stringtype){if("americano".equals(type)){returnnewAmericano();}elseif("latte".equals(type)){returnnewLatte();}else{thrownewIllegalArgumentException("没有这种咖啡");}}}// 4. 咖啡店(客户端)publicclassCoffeeStore{publicCoffeeorderCoffee(Stringtype){// 咖啡店不自己生产,交给工厂Coffeecoffee=SimpleCoffeeFactory.createCoffee(type);coffee.make();returncoffee;}}

📊 优缺点分析

  • 优点:客户端(CoffeeStore)免除了直接创建对象的职责,解除了与具体产品的耦合。
  • 缺点:违背了开闭原则。每增加一种咖啡,都要修改SimpleCoffeeFactory里的if-else。工厂类的职责过重。

工厂方法模式

为了解决简单工厂违背开闭原则的问题,我们升级一下。

💡 核心思想

定义一个用于创建对象的接口(抽象工厂),让子类决定实例化哪个类。将对象实例化推迟到子类。

🛠️ 代码实现

// 1. 抽象工厂接口publicinterfaceCoffeeFactory{CoffeecreateCoffee();}// 2. 具体工厂实现publicclassAmericanoFactoryimplementsCoffeeFactory{@OverridepublicCoffeecreateCoffee(){returnnewAmericano();}}publicclassLatteFactoryimplementsCoffeeFactory{@OverridepublicCoffeecreateCoffee(){returnnewLatte();}}// 3. 咖啡店(客户端)publicclassCoffeeStore{// 聚合工厂接口,不再依赖具体工厂privateCoffeeFactoryfactory;publicCoffeeStore(CoffeeFactoryfactory){this.factory=factory;}publicCoffeeorderCoffee(){Coffeecoffee=factory.createCoffee();coffee.make();returncoffee;}}

客户端调用:

// 想喝美式,就开一家美式工厂注入进去CoffeeStorestore=newCoffeeStore(newAmericanoFactory());store.orderCoffee();// 想喝拿铁,换一家拿铁工厂store=newCoffeeStore(newLatteFactory());store.orderCoffee();

📊 优缺点分析

  • 优点:完美符合开闭原则。新增咖啡种类?只需要新增一个Coffee实现类和一个对应的CoffeeFactory实现类,完全不用改原有代码!
  • 缺点:类的数量成倍增加(每个产品对应一个工厂)。在系统复杂度较低时,这种设计显得有些“重”。

抽象工厂模式

如果现在需求又升级了:咖啡店不仅要卖咖啡,还要卖甜点!而且美式要配提拉米苏,拿铁要配抹茶蛋糕(它们是有组合关系的)。
这时候用工厂方法就需要建一堆工厂,管理起来很乱。抽象工厂登场!

💡 核心思想

提供一个创建一系列相关或相互依赖对象的接口,而不指定它们具体的类。

🛠️ 代码实现

// 1. 定义甜点接口publicinterfaceDessert{voidshow();}// 2. 具体甜点publicclassTiramisuimplementsDessert{@Overridepublicvoidshow(){System.out.println("意大利提拉米苏");}}publicclassMatchaCakeimplementsDessert{@Overridepublicvoidshow(){System.out.println("抹茶蛋糕");}}// 3. 抽象工厂 (现在是产品族的工厂了)publicinterfaceItalianDessertFactory{CoffeecreateCoffee();DessertcreateDessert();}// 4. 具体工厂 (美式风味工厂)publicclassAmericanStyleFactoryimplementsItalianDessertFactory{@OverridepublicCoffeecreateCoffee(){returnnewAmericano();}@OverridepublicDessertcreateDessert(){returnnewTiramisu();}}// 5. 具体工厂 (拿铁风味工厂)publicclassLatteStyleFactoryimplementsItalianDessertFactory{@OverridepublicCoffeecreateCoffee(){returnnewLatte();}@OverridepublicDessertcreateDessert(){returnnewMatchaCake();}}

客户端调用:

// 买一套美式风味套餐ItalianDessertFactoryfactory=newAmericanStyleFactory();Coffeecoffee=factory.createCoffee();Dessertdessert=factory.createDessert();coffee.make();dessert.show();

📊 优缺点分析

  • 优点:当一个产品族(如咖啡+甜点)需要一起使用时,它能保证客户端始终使用同一个族中的对象。
  • 缺点:规定了所有可能被创建的产品集合,扩展新产品(比如新增“杯子”维度)非常困难,需要修改抽象工厂接口及其所有实现类,严重违背开闭原则。

🧠 总结与对比

别被这三个名字绕晕,记住下面这张表:

模式核心特征if-else在哪?扩展新产品扩展新产品族适用场景
简单工厂一个具体工厂,生产所有产品在工厂类里需改工厂代码不支持产品少,逻辑简单
工厂方法一个抽象工厂,每个产品一个具体工厂没有了增加具体工厂即可不支持产品种类经常扩展
抽象工厂一个抽象工厂,生产一个产品族没有了非常困难增加具体工厂即可固定的产品族体系(如UI换肤)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/28 5:00:27

Voxtral-4B-TTS-2603镜像免配置教程:7860端口Web工具页零依赖运行原理

Voxtral-4B-TTS-2603镜像免配置教程:7860端口Web工具页零依赖运行原理 1. 快速了解Voxtral语音合成 Voxtral-4B-TTS-2603是Mistral团队开源的一款专业级语音合成模型,特别适合需要高质量语音输出的应用场景。想象一下,你只需要输入文字&…

作者头像 李华
网站建设 2026/4/28 4:59:24

多平台送检AI率高怎么办:嘎嘎降AI一次到位实测2026

多平台送检AI率高怎么办:嘎嘎降AI一次到位实测2026 学校用知网,导师私下让过维普,期刊编辑要求附万方报告——这种"一稿三检"的情况在 2026 年 4 月已经不稀奇。投稿前一夜面对三份红字报告,最怕的事情是处理一遍只过一…

作者头像 李华
网站建设 2026/4/28 4:55:42

mPLUG-Owl3-2B Streamlit界面性能优化:首屏加载提速60%的4个关键配置

mPLUG-Owl3-2B Streamlit界面性能优化:首屏加载提速60%的4个关键配置 基于mPLUG-Owl3-2B多模态模型开发的本地图文交互工具,针对模型原生调用的各类报错做全维度修复,适配消费级GPU轻量化推理,采用Streamlit搭建聊天式交互界面&am…

作者头像 李华
网站建设 2026/4/28 4:53:22

Claude代码桥接器:让AI模型安全执行本地文件与命令的实战指南

1. 项目概述与核心价值最近在尝试将大型语言模型(LLM)的能力深度集成到我的本地开发工作流中时,遇到了一个普遍痛点:如何让像Claude这样的模型,不只是通过聊天窗口给我一些代码片段,而是能真正“动手”操作…

作者头像 李华