设计模式之工厂方法模式(Factory Method Pattern)
目录
- 1.1、前言
- 1.2、工厂方法模式简介
- 1.2.1、工厂方法模式的主要特点
- 1.2.2、工厂方法模式的主要结构
- 1.2.3、使用工厂方法模式的好处
- 1.3、SpringBoot中那些场景使用了工厂方法模式
- 1.4、日常工作中那些业务场景可以使用工厂方法模式
- 1.5、工厂方法模式实战(以某商场一次促销活动为例)
- 1.5.1、实战场景简介
1.1、前言
在开篇讲工厂方法模式之前我们来看一个场景小故事,女娲补天的故事大家都听说过吧,今天不说这个,说女娲创造人的故事,可不是“造人”的工作,这个词被现代人滥用了。这个故事是说,女娲在补了天后,下到凡间一看,哇塞,风景太优美了,天空是湛蓝的,水是清澈的,空气是清新的,太美丽了,然后就待时间长了就有点寂寞了,没有动物,这些看的到都是静态的东西呀,怎么办?
别忘了是神仙呀,没有办不到的事情,于是女娲就架起了八卦炉(技术术语:建立工厂)开始创建人,具体过程是这样的:先是泥巴捏,然后放八卦炉里烤,再扔到地上成长,但是意外总是会产生的:
第一次烤泥人,兹兹兹兹,感觉应该熟了,往地上一扔,biu~,一个白人诞生了,没烤熟!
第二次烤泥人,兹兹兹兹兹兹兹兹,上次都没烤熟,这次多烤会儿,往地上一扔,嘿,熟过头了,黑人哪!
第三次烤泥人,兹~ 兹~ 兹~,一边烤一边看着,嘿,正正好,Perfect!优品,黄色人种!
其实这个过程还是比较有意思的,如果我们要用程序去实现类似这样的业务场景的话,大家会用什么方式呢?大多数人会说⽤ifelse语句呀,很简单的。就业务场景而言使用ifelse语句来实现确实没什么问题,但是如果有一天女娲一时兴起想造“火星人”、“开普勒-10b人”、“比邻星人”等一系列外星人又该怎么办呢?大多数人还会说继续⽤ifelse语句呀,很简单的。我只想说这样编码下去只能是编码⼀时爽,重构⽕葬场。这也许是造成“屎山”代码和很多⼈并不愿意接⼿别⼈的代码的原因吧。
好的代码不只为了完成现有功能,也会考虑后续扩展。在结构设计上松耦合易读易扩展,在领域实现上⾼内聚不对外暴漏实现细节不被外部干扰。工厂方法模式在这方面有着先天的优势,工厂方法模式也能更合理的实现上述女娲造人的业务场景。
1.2、工厂方法模式简介
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它提供了一种创建对象的接口,但实际创建对象的工作由子类完成。这种模式的主要目的是降低类之间的耦合度,增强类的独立性,并提高系统的可维护性和可扩展性。
1.2.1、工厂方法模式的主要特点
- 分离了算法和对象创建:通过工厂方法,我们可以将对象的创建和使用分离,使得代码更加清晰和易于维护。
- 实现多态:工厂方法允许子类实现自己的行为,从而支持不同的创建策略。
- 避免使用new关键字:工厂方法模式通过工厂方法代替new关键字,可以减少错误,并提高代码的可读性和可维护性。
1.2.2、工厂方法模式的主要结构
- 工厂(Factory):负责创建对象,但不暴露如何创建对象的实现细节。
- 抽象产品(Product):定义了产品对象的行为,但不暴露如何创建对象。
- 具体产品(Concrete Product):实现了抽象产品定义的行为,并提供了创建对象的实际逻辑。
- 客户端(Client):使用工厂来获取产品对象,并调用产品对象的行为。
1.2.3、使用工厂方法模式的好处
- 简化客户端代码:客户端只需要知道如何使用工厂来获取对象,而不需要知道对象的创建细节。
- 提高代码的可扩展性:当需要添加新的产品类型时,只需要创建一个新的具体产品类和相应的工厂类即可,而不需要修改客户端代码。
- 降低类之间的耦合度:通过工厂方法模式,可以将对象的创建和使用分离,使得各个类之间的依赖关系更加清晰,提高了系统的可维护性和可扩展性。
总之,工厂方法模式是一种常用的设计模式,它通过提供一种统一的接口来创建对象,降低了类之间的耦合度,提高了代码的可扩展性和可维护性。
1.3、SpringBoot中那些场景使用了工厂方法模式
-
Bean的创建:在Spring Boot中,通过工厂方法模式可以实现Bean的创建。Spring提供了一种方式让我们自定义Bean的创建逻辑,即通过实现FactoryBean接口或使用@Bean注解来创建Bean。这样可以更灵活地控制Bean的创建过程,实现定制化的Bean创建逻辑。
-
RestTemplate的创建:在Spring Boot中,RestTemplate是用于调用Restful服务的类,它通常会被注入到各个服务中。RestTemplate的创建可以通过工厂方法模式来实现,将RestTemplate的创建逻辑封装在一个工厂类中,并通过工厂方法来获取RestTemplate对象,从而实现灵活配置和管理RestTemplate。
-
数据源的创建:在Spring Boot中,数据源是应用程序连接数据库的关键组件。通过工厂方法模式,可以将数据源的创建过程封装在一个工厂类中,根据不同的配置信息来创建不同的数据源对象,实现多数据源的管理和灵活切换。
-
事件监听器的创建:在Spring Boot中,事件监听器用于监听应用程序内部的各种事件,如请求处理、对象创建销毁等。通过工厂方法模式,可以实现事件监听器的灵活创建和管理,将事件监听器的创建逻辑封装在工厂类中,并通过工厂方法来获取监听器对象。
总之,工厂方法模式在Spring Boot中经常被用于Bean的创建、RestTemplate的创建、数据源的创建、事件监听器的创建等场景中,通过工厂方法模式可以实现对象的灵活创建和管理,提高代码的可扩展性和可维护性。
1.4、日常工作中那些业务场景可以使用工厂方法模式
在日常工作中,工厂方法模式可以应用于多种业务场景,尤其是当需要在不同的条件下创建不同类型的对象时。以下是一些典型的业务,适合使用工厂方法模式:
-
配置管理:当系统需要根据不同的环境(如开发、测试、生产)创建不同配置对象时,可以使用工厂方法模式。例如,不同环境的数据库连接配置、缓存配置等。
-
数据导出:在需要将数据导出到不同格式(如CSV、Excel、PDF)的场景中,工厂方法模式可以用来创建导出器对象。
-
消息发送:类似邮件发送的示例,当系统需要根据不同的消息类型(如短信、邮件、站内通知)创建不同的消息发送器时,工厂方法模式非常适用。
-
服务集成:在微服务架构中,不同的服务可能需要集成不同的第三方服务。使用工厂方法模式可以创建特定的服务集成器实例。
-
对象池管理:在需要对象池(如数据库连接池、线程池)的场景中,工厂方法模式可以帮助实现对象的复用和管理。
-
插件系统:当系统需要动态加载和创建插件时,工厂方法模式可以用来创建插件实例,而不需要修改插件本身的代码。
-
依赖注入:在Spring等框架中,工厂方法模式可以用来创建和注入依赖对象。例如,通过实现
FactoryBean
接口来定义自己的Bean创建逻辑。 -
异常处理:在需要根据不同的异常类型创建不同策略的场景中,工厂方法模式可以帮助定义不同的异常处理器。
-
资源管理:在需要根据不同资源类型(如文件、数据库记录)创建不同资源处理对象的场合,工厂方法模式可以提供一种灵活的解决方案。
-
UI组件创建:在Web应用开发中,根据用户配置或屏幕尺寸创建不同的UI也是工厂方法模式的适用场景。
工厂方法模式的优点在于它提供了一个接口,允许子类决定实例化哪个类,使得实例化的过程延迟到子类中进行,增强了程序的灵活性和可扩展性。在设计系统时,如果预计到会有多种类型的对象需要创建,并且创建逻辑可能会随着时间变化,那么工厂方法模式是一个很好的选择。
1.5、工厂方法模式实战(以某商场一次促销活动为例)
1.5.1、实战场景简介
某地一商店为了回馈老客户,针对满足条件的老客户发放对话卡、实物商品、优惠券三种奖品。其业务场景图如下:
大家可以提前想一想使用工厂方法模式如何实现上述业务场景,具体实现过程详见下一篇博文工厂方法模式实战之某商场一次促销活动。
相关文章:

设计模式之工厂方法模式(Factory Method Pattern)
目录 1.1、前言1.2、工厂方法模式简介1.2.1、工厂方法模式的主要特点1.2.2、工厂方法模式的主要结构1.2.3、使用工厂方法模式的好处 1.3、SpringBoot中那些场景使用了工厂方法模式1.4、日常工作中那些业务场景可以使用工厂方法模式1.5、工厂方法模式实战(以某商场一…...

API接口设计的18条规范
API接口设计的18条规范 签名 目的:防止数据被篡改 实现方法: 接口请求方将请求参数、时间戳和密钥拼接成一个字符串使用MD5等hash算法生成签名sign在请求参数或请求头中增加sign参数,传递给API接口API接口网关服务验证传递的sign值&#…...

adb简单使用命令
1. 查看当前连接的设备 adb devices 2. 文件路径 adb install apk 注意文件路径中不能有中文 3. adb shell ps Toplogcatlogcat可以结合greplogcat *:w 显示警告级别以上de 4. adb uninstall 软件名 1.软件名如何查看? 使用命令adb shell pm list packages会…...

构建 deno/fresh 的 docker 镜像
众所周知, 最近 docker 镜像的使用又出现了新的困难. 但是不怕, 窝们可以使用曲线救国的方法: 自己制作容器镜像 ! 下面以 deno/fresh 举栗, 部署一个简单的应用. 目录 1 创建 deno/fresh 项目2 构建 docker 镜像3 部署和测试4 总结与展望 1 创建 deno/fresh 项目 执行命令…...

数据库 | 数据库设计的步骤
1.需求分析 调查机构情况与熟悉业务活动,明确用户的需求,确定系统的边界,生成数据字典和用户需求规格说明书 2.概念结构设计 将从需求分析中得到的用户需求抽象为概念模型,设计E-R模型 3.逻辑结构设计 将E-R图转换为和DBMS相…...

改进YOLO系列 | CVPR 2021 | Involution:超越convolution和self-attention的神经网络算子
Involution:超越卷积和自注意力的新型神经网络算子(中文综述) 简介 Involuton是CVPR 2021上提出的新型神经网络算子,旨在超越卷积和自注意力,提供更高效、更具表达力的特征提取能力。 Involution原理 Involution的…...

落地速度与效果之争,通用VS垂直,我的观点和预测。
标题:AI大模型战场:通用VS垂直,谁将领跑落地新纪元? 摘要:随着人工智能技术的飞速发展,大模型的应用场景日益广泛。在这场竞赛中,通用大模型和垂直大模型各有优势,落地速度和可能性也…...

【Android面试八股文】在Android中,出现ClassNotFound的有可能的原因是什么?
在Android环境下类未找到的可能原因 在Android环境下,类未找到的可能原因包括但不限于以下几点: 类路径问题:Android应用使用的类通常存储在APK文件中。如果类所在的APK文件没有被正确加载,或者应用的类路径配置有误,就会导致类未找到的错误。 多DEX文件加载问题:在一些…...

模板引擎与 XSS 防御
在 View 层,可以解决 XSS 问题。在本书的“跨站脚本攻击”一章中,阐述了“输入检查” 与“输出编码”这两种方法在 XSS 防御效果上的差异。XSS 攻击是在用户的浏览器上执行的, 其形成过程则是在服务器端页面渲染时,注入了恶意的 H…...

vue3轮播图怎么做
先看效果 实现代码 <n-carouseleffect"card"dot-type"line"draggable:autoplay"!isHovered":current-index"currentIndex"prev-slide-style"transform: translateX(-150%) translateZ(-450px);opacity:1"next-slide-st…...

ubuntu中安装docker并换源
使用 Ubuntu 的仓库安装 Docker sudo apt update现在,你可以使用以下命令在 Ubuntu 中安装 Docker 以及 Docker Compose: sudo apt install docker.io docker-composeDocker 包被命名为 docker.io,因为在 Docker 出现之前就已经存在一个名为…...

HTML静态网页成品作业(HTML+CSS)—— 环保主题介绍网页(5个页面)
🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有5个页面。 二、作品演示 三、代…...

深入了解RSA加密算法
目录 前言 一、什么是RSA? 二、RSA加密的基本概念 1.非对称加密 2.密钥生成 3.加密和解密 三、RSA加密的工作原理 四、RSA的应用场景 五、RSA加密解密的实现 六、RSA算法的局限性及改进措施 前言 在当今的数字化时代,信息的安全性成为了人们关注…...

github基础使用
前言 将用到的github指令记录下来,持续更新,方便随时查找学习。 一、github用到的指令 1、我们从github克隆下来的代码版本一般都是master主分支,我们要建立自己的分支进行修改: //git branch //查看目前的分支/* * master /…...

Docker使用心得
Docker使用心得 最近使用Docker比较频繁,特此想记录一下,方便后续查找。 Docker常用命令Docker如何配置使用GPU环境?如何使用Dockerfile构建镜像?如何使用docker compose 实例化容器? Docker如何配置使用GPU环境 参…...

QListWidget 插入 item,item显示自定义界面
代码示意: class ItemWidget_action_cfg_w(QWidget):... # 如下方法是在指定item下插入新的item def __do_add_item(self, item):# 获取当前item rowrow self.__list_w.indexFromItem(item).row()# 注意这里没有父类,解释见后面说明new_item QList…...

Python写一个ERP系统和agent智能体协同仓库和订单的案例
这是一个关于使用Python编写一个简单的ERP系统,并与Agent智能体协同完成仓库和订单管理的案例。在这个案例中,我们将使用Python的第三方库sqlite3进行数据库操作,以及discord库实现与Agent智能体的通信。 1. 首先,安装所需库&…...

【计算机网络】已解决:“‘ping‘ 不是内部或外部命令,也不是可运行的程序或批处理文件”报错
文章目录 一、问题分析背景二、可能出错的原因三、错误代码示例四、正确解决方法与示例五、注意事项 已解决“‘ping’ 不是内部或外部命令,也不是可运行的程序或批处理文件”报错 一、问题分析背景 在Windows操作系统中,ping 命令是一个常用的网络诊断…...

Web前端学堂:深入探索前端开发的核心领域
Web前端学堂:深入探索前端开发的核心领域 在数字化时代的浪潮中,Web前端开发扮演着至关重要的角色。它不仅是连接用户与互联网世界的桥梁,更是创造丰富、互动网络体验的关键所在。本文将带领读者走进Web前端学堂,从四个方面、五个…...

Java数据结构与算法(0/1背包问题)
前言: 背包问题(Knapsack Problem)是组合优化问题中的一个经典问题,有多个变种。这里我们讨论的是 0/1 背包问题,这是最基本的一种形式。问题的描述如下: 给定 n 件物品,每件物品有一个重量 wi 和一个价值…...

LLVM 中 的 pass 及其管理机制
概述 LLVM 编译器框架的核心概念是任务调用和执行 编译器开发者将IR分解为不同的处理对象,并将其处理过程实现为单独的pass类型。在编译器初始化,pass被实例化,并被添加到pass管理中 pass 管理器(pass manager) 以流水线的方式将各个独立的…...

第 5 章 监控系统 | 入门案例 - 虚拟机监控
👉 本文目标:为 Linux 虚拟机/服务器安装 node_exporter,实现对虚拟机/服务器的监控。 👀 本文内容: 安装 Node Exporter,暴露 Linux 指标(比如 CPU、磁盘、IO 等)配置 Prometheus 抓取 Node Exporter 暴露的指标数据配置 Recording Rule,便于缓存/加速 Dashboard 频…...

教资认定报名照片要求小于190kb…
教资认定报名照片要求小于190kb…… 要求:文件小于190kb,宽度290-300,高度408-418 方法:vx搜随时照-教资认定 直接制作合规尺寸即可,还可以打印纸质版邮寄到家...

显示类控件——Calendar Widget
🐌博主主页:🐌倔强的大蜗牛🐌 📚专栏分类:QT ❤️感谢大家点赞👍收藏⭐评论✍️ 文章目录 一、Calendar Widget介绍核心属性重要信号代码示例: 获取选中的日期 一、Calendar Widget 介绍 …...

system与excel族函数区别
1.system #include<stdlib.h> int system(const char *command); comand是命令的路径,一般我们用绝对路径 system函数会创建新的进程,新的进程执行完返回原来的进程,原来的进程则继续执行后面的代码段。 如我们创建一个sys.cpp文件…...

STM32存储左右互搏 模拟U盘桥接SPI总线FATS读写FLASH W25QXX
STM32存储左右互搏 模拟U盘桥接SPI总线FATS读写FLASH W25QXX STM32的USB接口可以模拟成为U盘,通过FATS文件系统对连接的存储单元进行U盘方式的读写。 这里介绍STM32CUBEIDE开发平台HAL库模拟U盘桥接SPI总线FATS读写W25Q各型号FLASH的例程。 FLASH是常用的一种非易失…...

jrt从量变到质变
又是一个加班的周末,上周把台式机代码和数据库环境弄好了,这周进行大数据测试,直接把标本、标本医嘱、报告、报告结果、药敏结果等数据插入到1亿的规模,跑了一天一夜插入了5000多万个标本,后面接着补剩下的到一亿。 演…...

NLP主流大模型如GPT3/chatGPT/T5/PaLM/LLaMA/GLM的原理和差异有哪些-详细解读
自然语言处理(NLP)领域的多个大型语言模型(如GPT-3、ChatGPT、T5、PaLM、LLaMA和GLM)在结构和功能上有显著差异。以下是对这些模型的原理和差异的深入分析: GPT-3 (Generative Pre-trained Transformer 3) 虽然GPT-4…...

从MySQL到NoSQL:分析传统关系型数据库与NoSQL数据库的协同
引言 数据库是一个系统,用来管理和存储数据的地方。数据在数据库中以一种结构化的方式组织,这样能更容易地查询和处理数据。 关系型数据库是基于关系模型的数据库,它将数据存储在不同的表中,每个表都有各自的独一无二的主键。表与表之间通过共享的数据项相互关联。像MySQ…...

三、树和割集
文章目录 1、树1.1 树的定义1.2 树的性质1.3 极小连通图1.4 树的中心1.5 生成树1.5.1 最小生成树 2、 割点和桥THE END 1、树 1.1 树的定义 \qquad 定义: 一个连通的无圈的图称为树。 \qquad 只有一个顶点的树叫做平凡树。 \qquad 树中度为1的节点称为叶子结点。…...