设计模式 - 工厂模式 精准梳理精准记忆


1、代码片段 - 带入理解
一、核心模式分类
- 简单工厂模式(编程习惯,非 GoF 设计模式)
- 工厂方法模式(GoF 创建型模式)
- 抽象工厂模式(GoF 创建型模式)
二、演变过程:咖啡店案例
初始实现
// 咖啡基类
abstract class Coffee {public abstract String getName();
}class AmericanCoffee extends Coffee {}
class LatteCoffee extends Coffee {}// 咖啡店直接创建对象
class CoffeeStore {public Coffee orderCoffee(String type) {if ("american".equals(type)) {return new AmericanCoffee();} else {return new LatteCoffee();}}
}
问题 违反开闭原则,新增咖啡类型需修改订单方法
三、改进方案演变
1、简单工厂模式
class SimpleCoffeeFactory {public Coffee createCoffee(String type) {// 创建逻辑...}
}class CoffeeStore {private SimpleCoffeeFactory factory;public Coffee orderCoffee(String type) {return factory.createCoffee(type);}
}
- 优点 解耦对象创建
- 缺点 仍需修改工厂代码,违反开闭原则
2、工厂方法模式
interface CoffeeFactory {Coffee createCoffee();
}class AmericanFactory implements CoffeeFactory {public Coffee createCoffee() { return new AmericanCoffee(); }
}class CoffeeStore {private CoffeeFactory factory;public void setFactory(CoffeeFactory factory) {this.factory = factory;}public Coffee orderCoffee() {return factory.createCoffee();}
}
- 优点 完全遵循开闭原则
- 缺点 类数量激增(类爆炸问题)
3、抽象工厂模式
interface DessertFactory {Coffee createCoffee();Dessert createDessert();
}class AmericanDessertFactory implements DessertFactory {public Coffee createCoffee() { return new AmericanCoffee(); }public Dessert createDessert() { return new MatchaMousse(); }
}
- 优点 管理产品族(咖啡+甜点的组合)
- 代价 新增产品类型需修改所有工厂接口
4、模式对比表
| 模式特性 | 简单工厂 | 工厂方法 | 抽象工厂 |
|---|---|---|---|
| 扩展性 | 修改工厂类 | 新增工厂子类 | 新增工厂实现类 |
| 产品维度 | 单一产品 | 单一产品 | 产品族(多相关产品) |
| 开闭原则 | 违反 | 遵循 | 部分遵循 |
| 复杂度 | 低 | 中 | 高 |
| 典型应用场景 | 简单对象创建 | 需要灵活扩展的产品创建 | 系列关联产品的组合创建 |
四、进阶应用技巧
1、静态工厂
class SimpleCoffeeFactory {public static Coffee createCoffee(String type) {// 创建逻辑...}
}
2、配置化工厂
# bean.properties
american=com.example.AmericanCoffee
latte=com.example.LatteCoffee
class ConfigFactory {private static Map<String, Coffee> cache = new HashMap<>();static {// 加载配置文件,反射创建对象存入缓存}public static Coffee getCoffee(String key) {return cache.get(key);}
}
全部代码
public class CoffeeFactory {// 加载配置文件, 获取配置文件中配置的全类名, 并创建该类的对象进行存储// 1.定义容器对象用来存储咖啡对象private static HashMap<String, Coffee> map = new HashMap<String, Coffee>();// 2.加载配置文件, 只需要加载一次static {// 2.1 创建proper.ties 对象Properties p = new Properties();// 2.2调用p对象中的load 方法进行配置文件的加载 获取字节码 -> 获取类加载器 -> 获取目标资源(返回inputStream)InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties");try {// 加载资源p.load(is);// 从p集合中获取全类名并创建对象Set<Object> keys = p.keySet();for (Object key : keys) {String className = p.getProperty((String) key);// 通过反射创建对象Class<?> clazz = Class.forName(className);Coffee coffee = (Coffee) clazz.newInstance();// 创建对象// 将名称和对象存储到容器中map.put((String) key,coffee);}} catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {e.printStackTrace();}}// 根据名称获取对象public static Coffee createCoffee(String name){return map.get(name);}
}
五、JDK典型案例
- 集合迭代器
// 工厂方法模式应用
Collection<String> coll = new ArrayList<>();
Iterator<String> it = coll.iterator(); // ArrayList内部实现Iterator
- 日期工具
Calendar cal = Calendar.getInstance(); // 根据时区返回不同实现
DateFormat df = DateFormat.getInstance();
2、文字提炼 - 记忆切入点
一、简单工厂模式
1、核心思想
将对象创建逻辑集中在一个"工厂类"中,通过 参数 控制具体产品类型。
-
关键步骤
-
定义产品接口
创建抽象基类(如Coffee),声明所有产品共有的方法(如getName()) -
实现具体产品
继承基类创建具体产品(如AmericanCoffee和LatteCoffee),各自实现特有逻辑 -
构建工厂类
创建SimpleCoffeeFactory类,内部包含静态/实例方法(如createCoffee(type)),通过if-else或switch判断参数类型,返回对应的具体产品实例 -
客户端调用
客户端(如CoffeeStore)持有工厂引用,调用createCoffee()时传入类型参数,无需直接接触具体产品类
-
-
典型特征
-
工厂类包含所有产品的创建逻辑
-
新增产品必须修改工厂类代码
-
二、工厂方法模式
2、核心思想
将对象的创建 延迟 到子类,每个产品对应一个专属工厂。
-
关键步骤
-
定义抽象工厂接口
创建CoffeeFactory接口,声明抽象方法(如createCoffee()) -
实现具体工厂
为每个产品创建专属工厂类(如AmericanCoffeeFactory和LatteCoffeeFactory),在createCoffee()中返回对应的具体产品实例 -
客户端依赖抽象
客户端类(如CoffeeStore)持有工厂接口的引用,通过setFactory()方法注入具体工厂 -
动态创建产品
客户端调用factory.createCoffee()时,实际执行的是具体工厂类中实现的创建逻辑
-
-
典型特征
-
每个产品对应一个独立工厂类
-
新增产品只需添加新工厂,无需修改已有代码
-
三、抽象工厂模式
2、核心思想
创建相关产品族的工厂,保证产品之间的兼容性。
-
关键步骤
-
定义产品族接口
创建多个抽象产品接口(如Coffee: 咖啡和Dessert: 甜点),每个接口代表一类产品 -
定义抽象工厂接口
创建DessertFactory: 甜点工厂接口,声明创建系列产品的方法(如createCoffee()和createDessert()) -
实现具体工厂
为每个产品族创建工厂类(如AmericanDessertFactory: 美式甜点工厂),同时实现该族内 所有产品的创建逻辑 -
客户端组合使用
客户端通过选择具体工厂,获得配套的产品组合(如美式咖啡 + 抹茶慕斯),确保产品间的兼容性
-
-
典型特征
-
一个工厂创建多个关联产品
-
新增产品类型时, 需要修改所有工厂接口
-
四、工厂模式历史演进
- 简单工厂 解决直接
new对象带来的耦合问题,但工厂本身成为新的耦合点 - 工厂方法 通过多态工厂解耦,支持扩展但容易产生类爆炸
- 抽象工厂 应对产品组合需求,用更高维度的抽象管理关联对象
五、记忆点 - 关键区别
-
考虑创建目标时
简单工厂单一产品工厂方法单一产品抽象工厂产品族
-
考虑扩展代价时
简单工厂修改工厂类工厂方法新增工厂类抽象工厂修改所有工厂接口
-
考虑设计重心时
简单工厂创建逻辑集中化工厂方法创建责任分散化抽象工厂产品组合约束
提炼
模式选择指南
- 简单工厂 适用于对象创建逻辑简单,不需要频繁扩展
- 工厂方法 适合需要灵活扩展产品类型的场景
- 抽象工厂 适用于管理产品族,强调相关产品必须配套使用
关键设计原则体现
- 开闭原则 工厂方法模式的典型体现
- 单一职责 每个工厂只负责创建特定对象
- 依赖倒置 客户端依赖抽象接口而非具体实现
如果这篇文章帮到你, 帮忙点个关注呗, 不想那那那点赞或收藏也行鸭 (。•̀ᴗ-)✧ ~

'(இ﹏இ`。)
相关文章:
设计模式 - 工厂模式 精准梳理精准记忆
1、代码片段 - 带入理解 一、核心模式分类 简单工厂模式(编程习惯,非 GoF 设计模式)工厂方法模式(GoF 创建型模式)抽象工厂模式(GoF 创建型模式) 二、演变过程:咖啡店案例 初始实现…...
NVIDIA(英伟达) GPU 芯片架构发展史
GPU 性能的关键参数 CUDA 核心数量(个):决定了 GPU 并行处理能力,在 AI 等并行计算类业务下,CUDA 核心越多性能越好。 显存容量(GB):决定了 GPU 加载数据量的大小,在 AI…...
springboot项目使用中创InforSuiteAS替换tomcat
springboot项目使用中创InforSuiteAS替换tomcat 学习地址一、部署InforSuiteAS1、部署2、运行 二、springboot项目打包成war包 特殊处理1、pom文件处理1、排除内嵌的tomcat包2、新增tomcat、javax.servlet-api3、打包格式设置为war4、打包后的项目名称5、启动类修改1、原来的不…...
八、Redis 过期策略与淘汰机制:深入解析与优化实践
Redis 过期策略与淘汰机制:深入解析与优化实践 Redis 作为基于内存的高性能数据库,如何管理过期的键(key)和当内存不足时如何淘汰数据,是影响 Redis 性能和稳定性的关键因素。本篇文章将深入解析 Redis 的过期 key 处理方式和数据淘汰策略,并结合实际应用场景,帮助开发…...
Tomcat-web服务器介绍以及安装部署
一、Tomcat简介 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。 Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用…...
C#释放内存空间的方法
目录 前言释放 C# 对象内存的六种方法1、手动释放内存空间2、使用 Using 语句3、使用 垃圾回收器4、GC.Collect() 方法5、GC.WaitForPendingFinalizers() 方法6、WeakReference 类 注意 前言 当不再需要对象时释放内存空间对于防止内存泄漏和提高应用程序性能至关重要。C# 提供…...
18类创新平台培育入库!长沙经开区2025年各类科技创新平台培育申报流程时间材料及申报条件
长沙经开区打算申报企业研发中心、技术创新中心、工程技术研究中心、新型研发机构、重点实验室、概念验证中心和中试平台、工程研究中心、企业技术中心、制造业创新中心、工业设计中心等创新平台的可先备案培育入库,2025年各类平台的认定将从培育库中优先推荐&#…...
使用 Elasticsearch 进行集成测试初始化数据时的注意事项
作者:来自 Elastic piotrprz 在创建应该使用 Elasticsearch 进行搜索、数据聚合或 BM25/vector/search 的软件时,创建至少少量的集成测试至关重要。虽然 “模拟索引” 看起来很诱人,因为测试甚至可以在几分之一秒内运行,但它们实际…...
PostgreSQL常用系统表
1.概念 * 系统表记录了数据库的各种信息,并由SQL命令关联的系统操作表操作会自动维护其中的内容。 * pg_catalog是postgres的系统表命名空间,用于存储系统函数和系统元数据,包含了所有的内置数据类型、函数、表、系统视图等。pg_catalog并不…...
9. Flink的性能优化
1. Flink的资源和代码优化 1.1 slot资源配置 Flink中具体跑任务的进程叫TaskManager,TM进程又会根据配置划分出诺干个TaskSlot,它是具体运行SubTask的地方。slot是Flink用来隔离各个subtask的资源集合,这里的资源一把指内存,TCP…...
【文生图】windows 部署stable-diffusion-webui
windows 部署stable-diffusion-webui AUTOMATIC1111 stable-diffusion-webui Detailed feature showcase with images: 带图片的详细功能展示: Original txt2img and img2img modes 原始的 txt2img 和 img2img 模式 One click install and run script (but you still must i…...
华为:Wireshark的OSPF抓包分析过程
一、OSPF 的5包7状态 5个数据包 1.Hello:发现、建立邻居(邻接)关系、维持、周期保活;存在全网唯一的RID,使用IP地址表示 2.DBD:本地的数据库的目录(摘要),LSDB的目录&…...
视频输入设备-V4L2的开发流程简述
一、摄像头的工作原理与应用 基本概念 V4L2的全称是Video For Linux Two,其实指的是V4L的升级版,是linux系统关于视频设备的内核驱动,同时V4L2也包含Linux系统下关于视频以及音频采集的接口,只需要配合对应的视频采集设备就可以实…...
python基础课程整理--元组的基础
好的,下面详细列举Python元组的特点,包括取值、增加、修改和删除操作: 元组(Tuple) 元组(Tuple)的特点如下: 定义:使用圆括号 () 包裹,可以存储多个元素。…...
Windows设置目录及子目录大小写不敏感暨git克隆报错同名文件已存在的解决办法
在Windows系统中设置目录及其子目录为大小写不敏感,可以通过以下步骤完成: 步骤说明: 以管理员身份运行命令提示符或PowerShell 右键点击“开始”菜单,选择“命令提示符(管理员)”或“Windows PowerShell&…...
浅论数据库聚合:合理使用LambdaQueryWrapper和XML
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、数据库聚合替代内存计算(关键优化)二、批量处理优化四、区域特殊处理解耦五、防御性编程增强 前言 技术认知点:使用 XM…...
CentOS 7.9 安装 ClickHouse 文档
1. 环境准备 确保系统为 CentOS 7.9,并已安装 Docker。如果未安装 Docker,请先安装 Docker。 安装 Docker # 卸载旧版本 Docker(如果有) sudo yum remove -y docker docker-client docker-client-latest docker-common docker-…...
WPS条件格式:B列的值大于800,并且E列的值大于B列乘以0.4时,这一行的背景标红
一、选择数据区域 选中需要应用条件格式的区域(例如A2:E100 )。 二、打开条件格式 点击“开始”选项卡,选择“条件格式” > “新建规则”。 三、选择规则类型 选择“使用公式确定要设置格式的单元格”。 四、输入公式 在公式框中输入以…...
SQL分几种
SQL(Structured Query Language)是用于管理关系型数据库的标准语言。根据功能,SQL 语句可以分为以下几类: 1. 数据查询语言(DQL,Data Query Language) 用于从数据库中查询数据。 核心语句&…...
MWC 2025 | 紫光展锐联合移远通信推出全面支持R16特性的5G模组RG620UA-EU
2025年世界移动通信大会(MWC 2025)期间,紫光展锐联合移远通信,正式发布了全面支持5G R16特性的模组RG620UA-EU,以强大的灵活性和便捷性赋能产业。 展锐芯加持,关键性能优异 RG620UA-EU模组基于紫光展锐V62…...
AI-Ollama本地大语言模型运行框架与Ollama javascript接入
1.Ollama Ollama 是一个开源的大型语言模型(LLM)平台,旨在让用户能够轻松地在本地运行、管理和与大型语言模型进行交互。 Ollama 提供了一个简单的方式来加载和使用各种预训练的语言模型,支持文本生成、翻译、代码编写、问答等多种…...
ios使用swift调用deepseek或SiliconFlow接口
调用SiliconFlow API 注册并获取API密钥:打开硅基流动平台官网Models,进行注册和认证。登录后,进入首页,点击左上角三个横杠,选择API密钥,生成密钥并复制。配置第三方应用:打开安装好的Chatbox…...
PROFINET转PROFIBUS从案例剖析网关模块的协议转换功能
一、 案例背景 在当下追求高效协同的工业自动化生产体系里,设备间的无缝互联互通堪称关键要素。某企业的生产车间中,有一台性能稳定的变频器,其配备的是PROFIBUS接口。与此同时,操控整个生产线的核心大脑——西门子1500 PLC&…...
VsCode/Cursor workbench.desktop.main.js 的入口
这个也是main函数开始的,下面就是最后一行代码,表示export出rSo 函数作为它的名字公开为main, 和dll export表有点像了。 export {rSo as main}; 其中rSO是 function rSo(i) {return new nSo(i).open() } nSO是一个类,应该是就是workbenchM…...
VEC系列-RabbitMQ 入门笔记
消息队列(MQ)对于开发者来说是一个经常听到的词汇,但在实际开发中,大多数人并不会真正用到它。网上已经有很多关于 MQ 概述和原理的详细讲解,官网文档和技术博客也都介绍得很深入,因此,我在这里…...
第5章 使用OSSEC进行监控(网络安全防御实战--蓝军武器库)
网络安全防御实战--蓝军武器库是2020年出版的,已经过去3年时间了,最近利用闲暇时间,抓紧吸收,总的来说,第5章开始进入主机安全(HIDS)领域了,2022年的时候有幸做过终端安全一段时间&a…...
安装IK分词器;IK分词器配置扩展词库:配置扩展字典-扩展词,配置扩展停止词字典-停用词
安装IK分词器;IK分词器配置扩展词库:配置扩展字典-扩展词,配置扩展停止词字典-停用词 安装IK分词器IK分词配置扩展词库配置扩展字典-扩展词配置停止词字典-停用词测试配置字典前配置字典后 本文 ElasticSearch 版本为:7.17.9&…...
cursor+deepseek实现完整的俄罗斯方块小游戏
<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>俄罗斯方块</title><style>body {margin: 0;display: flex;justify-content: center;align-items: center;height: 100vh;background: …...
Oracle 数据库基础入门(五):限制查询与范式三约定深度解析
在 Oracle 数据库的学习进程中,限制查询与范式三约定是两个极为重要的概念。限制查询帮助我们精准获取特定范围的数据,而范式三约定则为数据库设计提供了科学的指导框架。对于 Java 全栈开发者而言,掌握这些知识不仅有助于高效地从数据库中提…...
pgsql行列转换
目录 一、造测试数据 二、行转列 1.函数定义 2.语法 3.示例 三、列转行 1.函数定义 2.语法 3.示例 一、造测试数据 create table test ( id int, json1 varchar, json2 varchar );insert into test values(1,111,{111}); insert into test values(2,111,222,{111,22…...
