设计模式之工厂方法模式(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 和一个价值…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
