【HeadFirst系列之HeadFirst设计模式】第5天之工厂模式:比萨店的秘密武器,轻松搞定对象创建!
工厂模式:比萨店的秘密武器,轻松搞定对象创建!
大家好,今天我们来聊聊设计模式中的工厂模式。如果你曾经为对象的创建感到头疼,或者觉得代码中到处都是 new 关键字,那么工厂模式就是你的救星!本文基于《Head First 设计模式》的工厂模式章节,带你从比萨店的故事中轻松掌握工厂模式的精髓,附上 Java 代码示例,让你彻底理解并爱上它!

1. 简单工厂模式:比萨店的起步
故事背景
小明开了一家比萨店,刚开始只有两种比萨:芝士比萨和素食比萨。每次接到订单,小明都会根据客户的需求,手动创建对应的比萨对象。
问题出现
随着生意越来越好,比萨的种类也越来越多。小明发现,每次新增一种比萨,都需要修改订单处理的代码。这不仅麻烦,还容易出错。
解决方案:简单工厂模式
小明决定引入简单工厂模式,将比萨的创建逻辑集中到一个工厂类中。这样,无论比萨种类如何变化,订单处理的代码都不需要修改。
代码实现
// 比萨接口
interface Pizza {void prepare();void bake();
}// 具体比萨:芝士比萨
class CheesePizza implements Pizza {@Overridepublic void prepare() {System.out.println("Preparing Cheese Pizza");}@Overridepublic void bake() {System.out.println("Baking Cheese Pizza");}
}// 具体比萨:素食比萨
class VeggiePizza implements Pizza {@Overridepublic void prepare() {System.out.println("Preparing Veggie Pizza");}@Overridepublic void bake() {System.out.println("Baking Veggie Pizza");}
}// 简单工厂
class SimplePizzaFactory {public Pizza createPizza(String pizzaType) {if (pizzaType.equals("cheese")) {return new CheesePizza();} else if (pizzaType.equals("veggie")) {return new VeggiePizza();} else {throw new IllegalArgumentException("Unknown pizza type");}}
}// 客户端代码
public class PizzaStore {public static void main(String[] args) {SimplePizzaFactory factory = new SimplePizzaFactory();Pizza pizza = factory.createPizza("cheese");pizza.prepare(); // 输出: Preparing Cheese Pizzapizza.bake(); // 输出: Baking Cheese Pizza}
}
优点
- 将对象的创建逻辑集中在一个类中,便于维护。
- 客户端与具体产品解耦。
缺点
- 违反“开闭原则”,新增产品时需要修改工厂类。
2. 工厂方法模式:扩展比萨帝国
故事背景
小明的比萨店越做越大,他决定开分店!每个分店都有自己的特色比萨,比如纽约风味芝士比萨和芝加哥风味素食比萨。
问题出现
如果继续使用简单工厂模式,每次新增分店都需要修改工厂类,这显然不够灵活。
解决方案:工厂方法模式
小明决定采用工厂方法模式,将比萨的创建延迟到子类。每个分店都可以实现自己的比萨创建逻辑。
代码实现
// 比萨接口
interface Pizza {void prepare();void bake();
}// 具体比萨:纽约风味芝士比萨
class NYCheesePizza implements Pizza {@Overridepublic void prepare() {System.out.println("Preparing NY Style Cheese Pizza");}@Overridepublic void bake() {System.out.println("Baking NY Style Cheese Pizza");}
}// 具体比萨:芝加哥风味素食比萨
class ChicagoVeggiePizza implements Pizza {@Overridepublic void prepare() {System.out.println("Preparing Chicago Style Veggie Pizza");}@Overridepublic void bake() {System.out.println("Baking Chicago Style Veggie Pizza");}
}// 工厂接口
abstract class PizzaStore {public Pizza orderPizza(String type) {Pizza pizza = createPizza(type);pizza.prepare();pizza.bake();return pizza;}// 工厂方法protected abstract Pizza createPizza(String type);
}// 具体工厂:纽约比萨店
class NYPizzaStore extends PizzaStore {@Overrideprotected Pizza createPizza(String type) {if (type.equals("cheese")) {return new NYCheesePizza();} else {throw new IllegalArgumentException("Unknown pizza type");}}
}// 具体工厂:芝加哥比萨店
class ChicagoPizzaStore extends PizzaStore {@Overrideprotected Pizza createPizza(String type) {if (type.equals("veggie")) {return new ChicagoVeggiePizza();} else {throw new IllegalArgumentException("Unknown pizza type");}}
}// 客户端代码
public class PizzaTest {public static void main(String[] args) {PizzaStore nyStore = new NYPizzaStore();Pizza pizza = nyStore.orderPizza("cheese"); // 输出: Preparing NY Style Cheese Pizza, Baking NY Style Cheese PizzaPizzaStore chicagoStore = new ChicagoPizzaStore();pizza = chicagoStore.orderPizza("veggie"); // 输出: Preparing Chicago Style Veggie Pizza, Baking Chicago Style Veggie Pizza}
}
优点
- 符合“开闭原则”,新增产品时只需扩展子类。
- 将对象的创建逻辑分散到子类,降低了耦合度。
缺点
- 类的数量会增加,系统复杂度提高。
3. 抽象工厂模式:比萨与饮料的完美搭配
故事背景
小明发现,客户不仅喜欢比萨,还喜欢搭配饮料。于是,他决定推出套餐,每个套餐包含一款比萨和一款饮料。
问题出现
如果使用工厂方法模式,比萨和饮料的创建逻辑会分散在不同的工厂中,难以保证它们之间的兼容性。
解决方案:抽象工厂模式
小明决定采用抽象工厂模式,将比萨和饮料的创建逻辑集中到一个工厂中,确保每个套餐的比萨和饮料是兼容的。
代码实现
// 比萨接口
interface Pizza {void prepare();
}// 饮料接口
interface Drink {void serve();
}// 具体比萨:纽约风味芝士比萨
class NYCheesePizza implements Pizza {@Overridepublic void prepare() {System.out.println("Preparing NY Style Cheese Pizza");}
}// 具体饮料:纽约风味可乐
class NYCoke implements Drink {@Overridepublic void serve() {System.out.println("Serving NY Style Coke");}
}// 具体比萨:芝加哥风味素食比萨
class ChicagoVeggiePizza implements Pizza {@Overridepublic void prepare() {System.out.println("Preparing Chicago Style Veggie Pizza");}
}// 具体饮料:芝加哥风味雪碧
class ChicagoSprite implements Drink {@Overridepublic void serve() {System.out.println("Serving Chicago Style Sprite");}
}// 抽象工厂接口
interface MealFactory {Pizza createPizza();Drink createDrink();
}// 具体工厂:纽约风味套餐
class NYMealFactory implements MealFactory {@Overridepublic Pizza createPizza() {return new NYCheesePizza();}@Overridepublic Drink createDrink() {return new NYCoke();}
}// 具体工厂:芝加哥风味套餐
class ChicagoMealFactory implements MealFactory {@Overridepublic Pizza createPizza() {return new ChicagoVeggiePizza();}@Overridepublic Drink createDrink() {return new ChicagoSprite();}
}// 客户端代码
public class MealTest {public static void main(String[] args) {MealFactory nyFactory = new NYMealFactory();Pizza pizza = nyFactory.createPizza();Drink drink = nyFactory.createDrink();pizza.prepare(); // 输出: Preparing NY Style Cheese Pizzadrink.serve(); // 输出: Serving NY Style CokeMealFactory chicagoFactory = new ChicagoMealFactory();pizza = chicagoFactory.createPizza();drink = chicagoFactory.createDrink();pizza.prepare(); // 输出: Preparing Chicago Style Veggie Pizzadrink.serve(); // 输出: Serving Chicago Style Sprite}
}
优点
- 可以创建一组相关的对象,保证它们之间的兼容性。
- 符合“开闭原则”,新增产品族时只需扩展工厂类。
缺点
- 类的数量会大幅增加,系统复杂度提高。
总结
工厂模式的核心思想是将对象的创建与使用分离,从而使得系统更加灵活和可维护。三种工厂模式各有优缺点:
- 简单工厂模式:适合创建逻辑简单的场景,但违反“开闭原则”。
- 工厂方法模式:通过子类实现对象的创建,符合“开闭原则”,但会增加类的数量。
- 抽象工厂模式:适合创建一组相关对象的场景,但系统复杂度较高。
在实际开发中,应根据具体需求选择合适的工厂模式,以达到代码的高内聚、低耦合。希望本文能帮助你更好地理解工厂模式,并在项目中灵活运用!
互动话题
你在项目中用过工厂模式吗?遇到过哪些问题?欢迎在评论区分享你的经验!
相关文章:
【HeadFirst系列之HeadFirst设计模式】第5天之工厂模式:比萨店的秘密武器,轻松搞定对象创建!
工厂模式:比萨店的秘密武器,轻松搞定对象创建! 大家好,今天我们来聊聊设计模式中的工厂模式。如果你曾经为对象的创建感到头疼,或者觉得代码中到处都是 new 关键字,那么工厂模式就是你的救星!本…...
Redis如何解决热Key问题
目录 **如何解决 Redis 的热 Key(Hot Key)问题?****解决方案** **1. 使用多级缓存****方案** **2. 进行 Key 预分片(Key Sharding)****方案** **3. 使用 Redis 复制机制(主从复制或集群)****方案…...
从开发到部署:EasyRTC嵌入式视频通话SDK如何简化实时音视频通信的集成与应用
嵌入式设备和视频综合管理平台均支持B/S架构。在B/S架构下,传统的视频观看方式依赖于微软的OCX控件,然而OCX控件的使用正面临越来越多的挑战: 首先,用户需要安装浏览器插件、调整浏览器安全级别,并允许ActiveX控件弹出…...
Zookeeper(58)如何在Zookeeper中实现分布式锁?
在 Zookeeper 中实现分布式锁是一种常见的用例。Zookeeper 提供了强一致性、高可用性的分布式协调服务,使得它非常适合用来实现分布式锁。以下是详细的步骤和代码示例,展示如何在 Zookeeper 中实现分布式锁。 1. Zookeeper 分布式锁的基本原理 Zookeep…...
Mac端homebrew安装配置
拷打了一下午o3-mini-high,不如这位博主的超强帖子,10分钟结束战斗 跟随该文章即可,2025/2/19亲测可行 mac 安装HomeBrew(100%成功)_mac安装homebrew-CSDN博客文章浏览阅读10w次,点赞258次,收藏837次。一直觉得自己写…...
Spring 接入 DeepSeek
引入依赖 <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency>2.yml配置 spring:ai:openai:api-key: sk-xxxxx // 填写自己申请的keybase-url: http…...
vscode将文件中行尾默认CRLF改为LF
安装prettier npm install --save-dev --save-exact prettier执行命令 npx prettier --write --end-of-line lf .即可将项目中的所有文件行尾序列格式改为lf *在你使用git拉取代码的时候,git会自动将代码当中与你当前系统不同的换行方式转化成你当前系统的换行方…...
python-leetcode 33.排序链表
题目: 给定链表的头结点head,请将其按升序排列,并返回排序后的链表 方法一:自顶向下归并排序 链表自顶向下归并排序的过程: 1.找到链表的中点,以中点为分界,将链表拆分成两个子链表。寻找链表的中点可以…...
【数据结构初阶第十二节】设计循环队列
云边有个稻草人-CSDN博客 必须有为成功付出代价的决心,然后想办法付出这个代价。 还有最后一道关于队列的习题,这题有点难,准备好迎接挑战吧! 目录 1.【题目】 2.实现循环队列推荐用数组,Why? 3.Q1:如…...
基于微信小程序的民宿短租系统设计与实现(ssm论文源码调试讲解)
第4章 系统设计 4.1系统设计的目标 系统设计的目标是满足用户的需求和满足系统实现所需要的所有要求。本系统收集了信息浏览、信息删除、信息添加、信息修改、信息查询为一体[17]。改变了用户民宿短租的方式,提高管理员管理效率以及用户预订的效率。为用户、房主提…...
使用 Jetty 构建 HTTPS 服务入门指南
在互联网安全越来越重要的今天,使用 HTTPS 为 Web 服务提供安全传输成为标准配置。Jetty 是一个高性能、易用且功能丰富的开源 Java HTTP 服务器和 Servlet 容器,能够轻松实现 HTTPS 支持。本文将结合代码实例,引导您快速搭建一个基于 Jetty 的 HTTPS 服务。 一、Jetty 简介…...
数据结构《图》
数据结构《图论》 图的性质 一、无向图(Undirected Graph) 定义 由一组顶点(Vertex)和一组无向边(Edge)构成。 每条无向边用一条无方向的线段连接两个顶点,记为 ( (u, v) ),其中…...
用Chrome Recorder轻松完成自动化测试脚本录制
前言 入门自动化测试,录制回放通常是小白测试首先用到的功能。而录制回放工具也一直是各大Web自动化测试必然会着重提供的一块功能。 早期WinRunner、QTP这样的工具,自动化测试可以说是围绕录制回放开展的。近年像Selenium也提供有录制工具 Selenium IDE,Playwright也包含…...
⭐️苹果电脑安装windows10双系统【详细图文步骤保姆级教程】【本教材适用于MAC台式机、笔记本MacBook air和pro】
苹果电脑安装windows10双系统【详细图文步骤保姆级教程】【本教材适用于MAC台式机、笔记本MacBook air和pro】 苹果电脑安装windows10双系统一、准备工作准备项1:U盘作为系统安装盘准备项2:您需要安装的系统镜像 二、启动转换助理步骤1:找到启…...
win10系统上的虚拟机安装麒麟V10系统提示找不到操作系统
目录预览 一、问题描述二、原因分析三、解决方案四、参考链接 一、问题描述 win10系统上的虚拟机安装麒麟V10系统提示找不到操作系统,报错:Operating System not found 二、原因分析 国产系统,需要注意的点: 需要看你的系统类…...
Java 大视界 -- 开源社区对 Java 大数据发展的推动与贡献(91)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
深入浅出C语言内存模型——高阶篇
在C语言编程的征途上,内存管理无疑是最具挑战性的部分之一。今天,我们将深入探讨C语言的内存模型,剖析其高级特性,并通过一系列案例,助你成为内存管理的佼佼者。本文为高阶篇,适合已经有一定C语言基础的读者…...
AI 百炼成神:逻辑回归, 垃圾邮件分类
第二个项目:逻辑回归垃圾邮件分类 项目代码下载地址:https://download.csdn.net/download/m0_56366541/90398247 项目目标 学习逻辑回归的基本概念。使用逻辑回归算法来实现垃圾邮件的分类。理解如何处理文本数据以及如何评估分类模型的性能。项目步骤 准备数据集 我们将使…...
MybatisPlus-扩展功能
逻辑删除乐观锁 MyBatisPlus从入门到精通-3(含mp代码生成器) Db静态工具类 Spring依赖循环问题 代码生成器 MybatisPlus代码生成器 枚举处理器 我们这里用int来存储状态 需要注解,很不灵活 希望用枚举类来代替这个Integer 这样的话我…...
《计算机视觉》——角点检测和特征提取sift
角点检测 角点的定义: 从直观上理解,角点是图像中两条或多条边缘的交点,在图像中表现为局部区域内的灰度变化较为剧烈的点。在数学和计算机视觉中,角点可以被定义为在两个或多个方向上具有显著变化的点。比如在一幅建筑物的图像…...
收藏备用|2026版AI Agent与Agentic AI彻底分清!
在2026年大模型技术持续狂飙的当下,“智能体”相关概念迎来爆发式增长,AI Agent和Agentic AI更是成为技术圈高频热词,但多数小白、甚至部分程序员都容易将二者混为一谈,踩坑走弯路。 其实二者的定位有着天壤之别:AI Ag…...
软考高项通关秘籍:用“故事串联法”搞定进度管理6个子过程ITTO(附记忆口诀)
软考高项通关秘籍:用“故事串联法”搞定进度管理6个子过程ITTO(附记忆口诀) 备考软考高项的朋友们,是否曾被进度管理中那些枯燥的输入、工具技术和输出(ITTO)搞得头大?今天我要分享一套独创的&q…...
告别激活烦恼:KMS_VL_ALL_AIO智能激活脚本全方位指南
告别激活烦恼:KMS_VL_ALL_AIO智能激活脚本全方位指南 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows和Office激活而反复折腾吗?每次重装系统后都要面对复杂…...
vue3+springboot校园活动管理系统的设计与实现
目录同行可拿货,招校园代理 ,本人源头供货商功能模块分析技术实现要点数据模型设计扩展功能建议项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作同行可拿货,招校园代理 ,本人源头供货商 功能模块分析 用户管理模块 用户注册与…...
如何永久备份QQ空间:简单三步保存你的数字青春回忆
如何永久备份QQ空间:简单三步保存你的数字青春回忆 【免费下载链接】QZoneExport QQ空间导出助手,用于备份QQ空间的说说、日志、私密日记、相册、视频、留言板、QQ好友、收藏夹、分享、最近访客为文件,便于迁移与保存 项目地址: https://gi…...
MAYA-W463-00B,融合双频Wi-Fi 6与蓝牙5.4 LE的无线模块
简介今天我要向大家介绍的是 u-blox 的无线模块——MAYA-W463-00B。它不仅支持 MU-MIMO 技术,还具备 Station(站点)、Access Point(接入点)以及 Wi-Fi Direct 等多种灵活的工作模式。与此同时,它还集成了符…...
告别网盘下载烦恼:八大网盘直链下载助手完整使用指南
告别网盘下载烦恼:八大网盘直链下载助手完整使用指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云…...
告别插件安装烦恼:Zotero插件市场让你3分钟完成插件管理革命
告别插件安装烦恼:Zotero插件市场让你3分钟完成插件管理革命 【免费下载链接】zotero-addons Zotero Add-on Market | Zotero插件市场 | Browsing, installing, and reviewing plugins within Zotero 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-addons …...
Android系统开发工程师(SW)偏SDK方向职位解析与面试指南
一、职位概述 1.1 工作职责总览 Android系统开发工程师偏SDK方向,是Android开发领域的关键角色,承担着丰富且重要的职责。 首要任务便是负责Android终端或平板系统的开发及维护工作。这意味着需要对Android系统的架构有深入的理解,能够确保系统的稳定运行,及时修复出现的…...
基于Chaboche物理约束与LSTM残差学习的316L不锈钢循环塑性灰箱本构建模研究
摘要:针对316L不锈钢循环塑性响应的非线性、路径依赖及滞回特征,传统经验本构模型在复杂加载条件下描述能力有限,纯数据驱动模型又缺乏物理可解释性。为兼顾物理意义与预测精度,本文提出一种基于Chaboche物理约束与LSTM残差学习的…...
