重修设计模式-创建型-工厂模式
重修设计模式-创建型-工厂模式
一、概述
工厂模式(Factory Pattern)是设计模式中非常基础且常用的一种模式,主要目的是通过封装对象的创建过程,从而实现代码的解耦和灵活性的提升。
工厂模式的核心思想
- 封装对象的创建:将对象的创建过程封装起来,使得客户端不必直接创建对象,而是通过工厂类来间接创建对象。
- 解耦:将对象的创建与使用分离,使得客户端只需要知道如何使用对象,而不需要知道如何创建对象。
- 提高扩展性:当需要增加新的产品类时,只需要增加一个具体的工厂类或产品类,而不需要修改原有代码,符合开闭原则(对扩展开放,对修改关闭)。
工厂模式又细分为三种类型,简单工厂、工厂方法和抽象工厂,其中工厂方法和抽象工厂被收录在23种设计模式中,而简单工厂被看做是工厂方法的一种特例。其实这三种工厂模式的原理和实现都非常简单,重点在于搞清应用场景,什么时候可以考虑使用工厂模式,又该用这三种类型的哪一种呢?
举个例子:
应用需要根据传入的路径去解析文件并显示,但文件可能有json、xml或yaml等格式,需要根据后缀名来创建解析实现类。
需求很简单,可以直接翻译成代码:
fun loadConfig(path: String): Config? {var parser : IRuleConfigParser? = nullif (path.endsWith("json", true)) {parser = JsonRuleParser()} else if (path.endsWith("xml", true)) {parser = XmlRuleParser()} else if (path.endsWith("yaml", true)) {parser = YamlRuleParser()}val config = parser?.parser(path)return config
}
但“根据文件后缀名创建解析器”的逻辑是相对独立的,可以将其抽成一个方法来复用,但其实还可以将这部分逻辑抽成一个类,让这个类来负责对象的创建,从而更符合单一职责原则,让代码更清晰,而抽出的类就是简单工厂模式了。
二、简单工厂(Simple Factory)
又称静态工厂方法模式(Static Factory Method Pattern),简单工厂模式不是一种设计模式,而更像是一种编程习惯。抽出的工厂类根据传入的参数,决定创建出哪一种类的实例。
下面用简单工厂封装一下对象创建的代码:
//简单工厂
class SimpleFactory {companion object {@JvmStaticfun create(path: String): IRuleConfigParser? {return if (path.endsWith("json", true)) {JsonRuleParser()} else if (path.endsWith("xml", true)) {XmlRuleParser()} else if (path.endsWith("yaml", true)) {YamlRuleParser()} else null}}
}
调用处:
fun loadConfig(path: String): Config? {val parser = SimpleFactory.create(path)val config = parser?.parser(path)return config
}
可以看到调用处代码非常简洁,创建代码都被封装到工厂类中了,开发中只要维护工厂代码即可。其实该例子创建的对象是可以复用的,那么还可以在工厂类中通过 map 缓存创建的对象,不必每次都创建新对象。同时 map 还可以取代 if-else 形式的代码:
//带缓存的简单工厂
class SimpleFactory {companion object {@JvmStaticprivate val cacheMap: HashMap<String, IRuleConfigParser> = hashMapOf("json" to JsonRuleParser(),"xml" to XmlRuleParser(),"yaml" to YamlRuleParser(),)@JvmStaticfun create(path: String): IRuleConfigParser? {val extension = getFileExtension(path)return cacheMap[extension]}@JvmStaticfun getFileExtension(filePath: String): String {//...解析文件名获取扩展名,比如rule.json,返回jsonreturn filePath.substringAfterLast('.', "")}}
}
简单工厂模式的问题是,如果需要扩展新的产品类,就需要修改工厂类的代码,违反了开闭原则,所以只适合改动不频繁的简单场景(设计原则没必要严格遵守,根据场景灵活使用才是目的)
这里的解析器创建只是简单的 new 了一个对象,如果解析器的创建流程变得复杂,那 create() 方法中的代码也会随之变得冗长,这种情况下可以把解析器复杂的创建逻辑进一步封装到各个工厂类中,这就成了工厂方法模式。
三、工厂方法(Factory Method)
工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法让类的实例化延迟到子类中进行。这种方式的好处是,新增产品类时,只需要增加一个具体的产品类和对应的具体工厂类,而不需要修改原有的工厂接口和工厂类。
下面使用工厂方法封装解析器创建流程:
//封装每个解析器的创建过程
interface IRuleConfigParserFactory {fun create(): IRuleConfigParser
}//Json解析器创建
class JsonParserFactory : IRuleConfigParserFactory {override fun create(): IRuleConfigParser {val parser = JsonRuleParser()//parser.xxx = xxx//...return parser}
}//Xml解析器创建
class XmlParserFactory: IRuleConfigParserFactory {override fun create(): IRuleConfigParser = XmlRuleParser()
}//Yaml解析器创建
class YamlParserFactory: IRuleConfigParserFactory {override fun create(): IRuleConfigParser = YamlRuleParser()
}//这里其实还是简单工厂
class MethodFactory {companion object {@JvmStaticfun create(path: String): IRuleConfigParser? {var parserFactory: IRuleConfigParserFactory? = nullif (path.endsWith("json", true)) {parserFactory = JsonParserFactory()} else if (path.endsWith("xml", true)) {parserFactory = XmlParserFactory()} else if (path.endsWith("yaml", true)) {parserFactory = YamlParserFactory()}return parserFactory?.create()}}
}
外部调用:
fun loadConfig(path: String): Config? {val parser = MethodFactory.create(path)val config = parser?.parser(path)return config
}
可以看到复杂的解析器创建逻辑被隔离到具体的工厂创建类中了,又用简单工厂简化了调用代码。可以发现,简单工厂侧重对分支代码的封装,而工厂方法更侧重隔离对象创建的复杂代码,两者还可以组合使用。
工厂方法缺点是,如果工厂不只是生产一种类型的对象,或者说创建的对象会根据多个维度分类,那工厂方法的实现类将会非常多,从而难以维护。如上面的例子,解析器除了根据文件格式分类,还增加了文件大小的维度,这时候需要实现的类就有 3 x 2 = 6个:
SmallJsonParserFactory
SmallXmlParserFactory
SmallYamlParserFactory
BigJsonParserFactory
BigXmlParserFactory
BigYamParserFactory
可见创建对象维度的增加会导致工厂类爆增,针对上面场景,就可以使用抽象工厂,让一个工厂可以生产不同类型的对象。
四、抽象工厂(Abstract Factory)
抽象工厂模式使用抽象的接口来创建一系列相关或相互依赖的对象,而无需指定它们具体的类。这种方式主要用于创建一组相互依赖或关联的对象,而不需要指定它们具体的类。
以上面新增文件大小维度举例,抽象出代码如下:
//抽象工厂
interface IConfigParserFactory {fun createJsonFactory(): IRuleConfigParserfun createXmlFactory(): IRuleConfigParserfun createYamlFactory(): IRuleConfigParser
}//大文件解析器
class ConfigBigParser: IConfigParserFactory {override fun createJsonFactory(): IRuleConfigParser {//再这里创建不同维度的产品类return JsonRuleParser()}override fun createXmlFactory(): IRuleConfigParser {return XmlRuleParser()}override fun createYamlFactory(): IRuleConfigParser {return YamlRuleParser()}
}//小文件解析器
class ConfigSmallParser: IConfigParserFactory {override fun createJsonFactory(): IRuleConfigParser {//..省略return JsonRuleParser()}override fun createXmlFactory(): IRuleConfigParser {//..省略return XmlRuleParser()}override fun createYamlFactory(): IRuleConfigParser {//..省略return YamlRuleParser()}
}
调用处代码:
fun loadConfig3(path: String): Config? {//可根据具体业务,通过抽象工厂创建不同的产品类,无须关心实现类val parser1 = ConfigBigParser()val parser2 = ConfigSmallParser()parser1.createJsonFactory()parser1.createXmlFactory()parser1.createYamlFactory()parser2.createJsonFactory()parser2.createXmlFactory()parser2.createYamlFactory()
}
抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。
总结
工厂模式是将对象创建的过程封装,创建对象的复杂代码被隔离到每个工厂内部消化,从而实现对象的创建与使用分离。不同工厂模式适用于不同的场景,选择哪种模式取决于具体的需求和场景。
相关文章:
重修设计模式-创建型-工厂模式
重修设计模式-创建型-工厂模式 一、概述 工厂模式(Factory Pattern)是设计模式中非常基础且常用的一种模式,主要目的是通过封装对象的创建过程,从而实现代码的解耦和灵活性的提升。 工厂模式的核心思想 封装对象的创建&#x…...
使用Cskin时候 遇到按钮有默认阴影问题解决
使用Cskin时候 遇到按钮有默认阴影 设置 DrawType 属性就可以了...
121.rk3399 uboot(2017.09) 源码分析1(2024-09-05)
参考源码 : uboot(2017.09) 硬件平台:rk3399 辅助工具:linux虚拟机,sourceinsight4,文件浏览器(可以使用samba访问),ultraeidt(查看bin文件比较方便) 说明:…...
【图论】虚树 - 模板总结
适用于解决一棵树中只需要用到少部分点的时候,将需要用到的点提出来单独建一棵树 /********************* 虚树 *********************/ struct edge {int to, next;int val; };struct Virtual_Tree {int n; // 点数int dfn[N]; // dfs序int dep[N]; // 深度int fa…...
[C#学习笔记]注释
官方文档:Documentation comments - C# language specification | Microsoft Learn 一、常用标记总结 1.1 将文本设置为代码风格的字体:<c> 1.2 源代码或程序输出:<code> 1.3 异常指示:<exception> 1.4 段落 <para> 1.5 换行&…...
c# checkbox的text文字放到右边
checkbox的text文字放到右边 实现方法如下图 特此记录 anlog 2024年9月2日...
【node.js】基础之修改文件
node.js 基础(一) node.js是什么? 上面这句话的意思就是:Node.js 是一个开源的,跨平台的javascript运行环境。通俗的说就是一个应用程序或者说是一个软件,可以运行javascript。 Node.js的作用: 开发服务器应用。 将数…...
Notepad++回车不自动补全
问题 使用Notepad时,按回车经常自动补全,但我们希望回车进行换行,而不是自动补全,而且自动补全使用Tab进行补全足够了。下文介绍设置方法。 设置方法 打开Notepad,进入设置 - 首选项 - 自动完成,在插入选…...
CSS线性渐变拼接,一个完整的渐变容器(div),要拆分成多个渐变容器(div),并且保持渐变效果一致
1 需求 一个有渐变背景的div,需要替换成多个渐变背景div拼接,渐变效果需要保持一致(不通过一个大的div渐变,其他子的div绝对定位其上并且背景透明来解决) 2 分析 主要工作: 计算完整div背景线性渐变时的…...
【60天备战软考高级系统架构设计师——第十天:软件设计与架构综合练习】
经过前十天的学习,我们已经了解了软件工程生命周期模型、需求分析与管理方法,以及软件设计与架构的核心内容。为了巩固这些知识点,今天我们将进行一个综合练习。 前十天学习内容回顾 第1-3天:软件工程概述 学习了软件生命周期模…...
2024.8.15(python管理mysql、Mycat实现读写分离)
一、python管理mysql 1、搭建主mysql [rootmysql57 ~]# tar -xf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz [rootmysql57 ~]# cp -r mysql-5.7.44-linux-glibc2.12-x86_64 /usr/local/mysql [rootmysql57 ~]# rm -rf /etc/my.cnf [rootmysql57 ~]# mkdir /usr/local/mysql…...
CMU 10423 Generative AI:lec2
文章目录 1 概述2 部分摘录2.1 噪声信道模型(Noisy Channel Models)主要内容:公式解释:应用举例: 2.2 n-Gram模型1. 什么是n-Gram模型2. 早期的n-Gram模型3. Google n-Gram项目4. 模型规模与训练数据5. n-Gram模型的局…...
恋爱相亲交友系统源码原生源码可二次开发APP 小程序 H5,web全适配
直播互动:平台设有专门的直播间,允许房间主人与其他异性用户通过视频连线的方式进行一对一互动。语音视频交流:异性用户可以发起语音或视频通话,以增进了解和交流。群组聊天:用户能够创建群聊,邀请自己关注…...
OceanBase 4.x 存储引擎解析:如何让历史库场景成本降低50%+
据国际数据公司(IDC)的报告显示,预计到2025年,全球范围内每天将产生高达180ZB的庞大数据量,这一趋势预示着企业将面临着更加严峻的海量数据处理挑战。随着数据日渐庞大,一些存储系统会出现诸如存储空间扩展…...
js 如何写构造函数 ,构造函数和普通函数有什么区别
在 JavaScript 中,构造函数是一种特殊的函数,用于初始化一个新创建的对象。构造函数通常用来创建具有相似属性和方法的对象实例。构造函数的主要特点是在调用时使用 new 关键字,这样就会创建一个新对象,并将其原型设置为构造函数的…...
MySQL-进阶篇-锁(全局锁、表级锁、行级锁)
文章目录 1. 锁概述2. 全局锁2.1 介绍2.2 数据备份2.3 使用全局锁造成的问题 3. 表级锁3.1 表锁3.1.1 语法3.1.2 读锁3.1.3 写锁3.1.4 读锁和写锁的区别 3.2 元数据锁(Meta Data Lock,MDL)3.3 意向锁3.3.1 案例引入3.3.2 意向锁的分类 4. 行级…...
c++懒汉式单例模式(Singleton)多种实现方式及最优比较
前言 关于C懒汉式单例模式的写法,大家都很熟悉。早期的设计模式中有代码示例。比如: class Singleton {private: static Singleton *instance;public: static Singleton *getInstance() {if (NULL instance)instance new Singleton();return instanc…...
Gartner《2024中国安全技术成熟度曲线》AI安全助手代表性产品:开发者安全助手D10
海云安关注到,近日,国际权威研究机构Gartner发布了《2024中国安全技术成熟度曲线》(Hype Cycle for Security in China,2024)报告。 在此次报告中,安全技术成熟度曲线将安全周期划分为技术萌芽期(Innovation Trigger)…...
奇安信椒图--服务器安全管理系统(云锁)
奇安信椒图–服务器安全管理系统(云锁) 椒图 奇安信服务器安全管理系统是一款符合Gartner定义的CWPP(云工作负载保护平台)标准、EDR(终端检测与响应)、EPP终端保护平台(终端保护平台ÿ…...
pointer-events,添加水印的一个小小点
场景:平平无奇一个水印图,这类功能实现:就是覆盖在整个可视div后,又加了一个div(使用定位canvas画一个水印图充当背景),可时我好奇的是,我使用控制台,选择对应的元素时&a…...
毕业论文“通关秘籍”:好写作AI的神奇魔法盒
毕业季的钟声敲响,对于众多即将毕业的大学生来说,毕业论文就像是一场必须跨越的“终极挑战”。从选题时的迷茫,到文献收集的繁琐,再到大纲搭建的纠结,每一步都让人头疼不已。不过别担心,好写作AI这位论文写…...
5个跨系统突破:Ext2Read让Windows无缝访问Linux分区的创新方案
5个跨系统突破:Ext2Read让Windows无缝访问Linux分区的创新方案 【免费下载链接】ext2read A Windows Application to read and copy Ext2/Ext3/Ext4 (With LVM) Partitions from Windows. 项目地址: https://gitcode.com/gh_mirrors/ex/ext2read 当运维工程师…...
Open UI5 源代码解析之886:OverflowToolbarButton.js
源代码仓库: https://github.com/SAP/openui5 源代码位置:src\sap.m\src\sap\m\OverflowToolbarButton.js OverflowToolbarButton.js 深度解析与项目作用说明 文件定位与总体价值 这个文件定义了一个控件:sap.m.OverflowToolbarButton。从代码体量看,它并不长,却属于…...
OpenClaw安全指南:Qwen3.5-9B模型下的权限管控实践
OpenClaw安全指南:Qwen3.5-9B模型下的权限管控实践 1. 为什么需要关注OpenClaw的安全管控? 去年冬天的一个深夜,我被一阵急促的硬盘读写声惊醒。打开终端查看,发现是OpenClaw正在疯狂扫描我的整个Documents文件夹——原来是我白…...
告别过曝欠曝!手把手教你用FPGA实现加权灰度均值自动曝光(附Verilog思路)
FPGA图像处理实战:基于加权灰度均值的自动曝光算法实现 在工业检测、安防监控和医疗影像等领域,CMOS传感器采集的图像质量直接影响后续分析和决策。但环境光照变化常导致图像过曝或欠曝,传统固定曝光方案难以应对复杂场景。本文将深入探讨如何…...
Python通达信数据获取完整指南:mootdx让金融数据分析变得简单高效
Python通达信数据获取完整指南:mootdx让金融数据分析变得简单高效 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx 还在为获取A股市场数据而烦恼吗?mootdx作为一款纯Python开…...
Python AOT不是“编译一次,到处运行”——2026最新glibc/musl/ARM64-v8a三重目标平台适配手册(含内核级sysctl调优参数)
第一章:Python AOT编译的本质误区与2026技术定位 Python 社区长期存在一个根深蒂固的认知偏差:将“生成机器码”等同于“实现真正意义上的 AOT 编译”。事实上,CPython 的字节码(.pyc)本质是解释器专用中间表示&#x…...
性能引擎: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, Scar, and…...
openpilot终极指南:快速实现300+车型自动驾驶辅助的完整方案
openpilot终极指南:快速实现300车型自动驾驶辅助的完整方案 【免费下载链接】openpilot openpilot is an operating system for robotics. Currently, it upgrades the driver assistance system on 300 supported cars. 项目地址: https://gitcode.com/GitHub_Tr…...
3步解决会议记录难题:给职场人士的离线语音转文字工具
3步解决会议记录难题:给职场人士的离线语音转文字工具 【免费下载链接】TMSpeech 腾讯会议摸鱼工具 项目地址: https://gitcode.com/gh_mirrors/tm/TMSpeech 发现问题:为什么会议记录总是让人头疼? 你是否经历过这样的场景࿱…...
