【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
角点检测 角点的定义: 从直观上理解,角点是图像中两条或多条边缘的交点,在图像中表现为局部区域内的灰度变化较为剧烈的点。在数学和计算机视觉中,角点可以被定义为在两个或多个方向上具有显著变化的点。比如在一幅建筑物的图像…...
终极Windows和Office激活指南:KMS_VL_ALL_AIO完全解决方案
终极Windows和Office激活指南:KMS_VL_ALL_AIO完全解决方案 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows系统激活烦恼吗?Office突然变成只读模式让你束手…...
如何在5分钟内免费搭建OBS RTSP服务器:完整配置指南
如何在5分钟内免费搭建OBS RTSP服务器:完整配置指南 【免费下载链接】obs-rtspserver RTSP server plugin for obs-studio 项目地址: https://gitcode.com/gh_mirrors/ob/obs-rtspserver 你是否想过将OBS Studio的专业直播内容直接推送到监控系统、智能电视或…...
JCSprout字符串优化终极指南:StringBuilder与StringBuffer性能对比
JCSprout字符串优化终极指南:StringBuilder与StringBuffer性能对比 【免费下载链接】JCSprout 👨🎓 Java Core Sprout : basic, concurrent, algorithm 项目地址: https://gitcode.com/gh_mirrors/jc/JCSprout 在Java开发中&#x…...
Windows Cleaner:3分钟告别C盘爆红,让你的电脑重获新生!
Windows Cleaner:3分钟告别C盘爆红,让你的电脑重获新生! 【免费下载链接】WindowsCleaner Windows Cleaner——专治C盘爆红及各种不服! 项目地址: https://gitcode.com/gh_mirrors/wi/WindowsCleaner 你是否曾经打开电脑&a…...
STM32缺货别慌!手把手教你无缝替换APM32F103C8T6(附完整测试报告)
STM32缺货危机下的无缝替代方案:APM32F103C8T6实战指南 芯片短缺风暴席卷全球电子行业,STM32系列微控制器价格飙升、交期延长,让无数嵌入式工程师陷入困境。面对项目交付压力,国产替代方案成为救命稻草。本文将带你深入探索APM32F…...
Intv_ai_mk11 操作系统原理问答助手:深入解析进程、线程与内存管理
Intv_ai_mk11 操作系统原理问答助手:深入解析进程、线程与内存管理 1. 计算机教学的新助手 计算机专业的学生们常常面临一个共同挑战:操作系统原理这门课既抽象又复杂。从进程调度算法到内存管理机制,从死锁条件到分页策略,每个…...
别再被NumPy的(2,)形状坑了!手把手教你用reshape和newaxis搞定广播错误
NumPy形状陷阱全解析:从广播错误到高维操作实战 如果你曾经在NumPy中看到过ValueError: operands could not be broadcast together with shapes (2,) (3,)这样的错误,然后盯着屏幕百思不得其解,那么这篇文章就是为你准备的。NumPy的形状(sha…...
LFM2.5-VL-1.6B结合SpringBoot开发企业级视觉API服务
LFM2.5-VL-1.6B结合SpringBoot开发企业级视觉API服务 1. 引言:当视觉大模型遇上企业级Java服务 想象一下这样的场景:电商平台每天需要处理数百万张商品图片的自动分类和打标,客服系统要实时识别用户上传的截图内容,生产线上的质…...
LFM2.5-1.2B-Instruct镜像免配置:预装transformers+gradio+unsloth
LFM2.5-1.2B-Instruct镜像免配置:预装transformersgradiounsloth 1. 模型概述 LFM2.5-1.2B-Instruct是一个1.2B参数量的轻量级指令微调大语言模型,专为边缘设备和低资源服务器设计。这个模型特别适合需要本地AI对话能力的场景,比如嵌入式AI…...
G-Helper终极指南:免费掌控华硕笔记本的完整解决方案
G-Helper终极指南:免费掌控华硕笔记本的完整解决方案 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Strix, Sca…...
