设计模式Java实现-工厂模式

✨这里是第七人格的博客✨小七,欢迎您的到来~✨

🍅系列专栏:设计模式🍅

✈️本篇内容: 工厂模式✈️

🍱本篇收录完整代码地址:https://gitee.com/diqirenge/design-pattern 🍱

楔子

记得刚入行的时候,听过一个段子,同样开发一个功能初级程序员要1天,中级程序员要2天,高级程序员要1个星期。当时以为是老油条划水(虽然肯定还是会划一点水,哈哈),但是其实更重要的还是设计思想的不同,经验丰富的程序员往往考虑的更多,不光是业务拓展性,更有程序拓展性。

需求背景

实现一个图片上传功能,逻辑很简单,就是把图片上传到对象存储,但是现在有两个服务商可以选择,他们分别是阿里云和腾讯云,并且现在没有敲定用哪一个,需要你先对接。他们提供的API各不相同,我们假设他们提供的API如下

渠道接口
阿里云void aliUpload(String fileName, String ossId, String token);
腾讯云String tencentUpload(String fileName, String base64, String appID, String appSecret);

分析设计

因为这2个接口的实现的定义不一样,所以我们最好能抽象出一个统一的接口,让子类去实现自己的业务逻辑,这样的好处是以后腾讯云有变更,就改腾讯云,阿里云有变更就改阿里云,两个子类互不影响(满足单一职责原则)。

又为了不让上层直接使用我们这个统一的方法,所以我们可以再抽象一个类,让他来决定用哪一个上传方式,相当于加了一层防腐,这里我们把他叫做工厂类(创建者与具体的业务解耦)。

再想一下拓展情况,如果以后又加一种上传方式,比如华为云,那我们修改起来也非常方便,只要再加一个子类就可以了,调用方可以不用变(满⾜开闭原则)。

UML图

根据分析设计,我们可以先画一个简单的UML图,后面通过UML图编码

工厂模式UML.png

模块名称

factory

模块地址

https://gitee.com/diqirenge/design-pattern/tree/master/src/main/java/com/run2code/design/creational/factory

模块描述

工厂模式代码示例

代码实现

1、首先我们模拟出两个外部接口

上传至oss

/*** 上传至oss* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/17*/
public class AliOss {public void aliUpload(String fileName, String ossId, String token) {System.out.println("ali upload 入参: " + fileName + " " + ossId + " " + token);System.out.println("ali 上传成功!");}
}

上传至cos

/*** 上传至cos* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/17*/
public class TencentCos {public String tencentUpload(String fileName, String base64, String appID, String appSecret) {System.out.println("tencent upload 入参: " + fileName + " " + base64 + " " + appID + " " + appSecret);return "成功上传到腾讯云";}
}

2、然后定义一个用于创建对象的接口或抽象类,让子类决定实例化哪一个类

抽象类

/*** 抽象的上传操作类,当然他也可以是一个接口* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/15*/
public abstract class BaseUpDownloader {/*** 执行文件上传操作(延迟到子类实现)** @param filePath 文件路径* @param fileName 文件名称* @param param    第三方参数* @return {@link String}*/public abstract String doUpload(String filePath, String fileName, Map<String, String> param);
}

上传子类 oss,继承了抽象类,并且调用了上传至oss的方法

/*** 上传子类 oss* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/15*/
public class AliOssUpDownloader extends BaseUpDownloader {private AliOss aliOss;public AliOssUpDownloader() {this.aliOss = new AliOss();}@Overridepublic String doUpload(String filePath, String fileName, Map<String, String> param) {aliOss.aliUpload(fileName, param.get("ossId"), param.get("token"));return "AliOssUpDownloader upload success";}
}

上传子类 cos,继承了抽象类,并且调用了上传至oss的方法

/*** 上传子类 cos,继承了抽象类,并且调用了上传至oss的方法* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/15*/
public class TencentUpDownloader extends BaseUpDownloader {private TencentCos tencentCos;public TencentUpDownloader() {this.tencentCos = new TencentCos();}@Overridepublic String doUpload(String filePath, String fileName, Map<String, String> param) {String result = tencentCos.tencentUpload(fileName, param.get("base64"), param.get("appID"), param.get("appSecret"));System.out.println(result);return "TencentUpDownloader upload success";}
}

3、创建一个工厂类,其中包含一个用于创建产品对象的方法。

/*** 上传的工厂类* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/17*/
public class UpDownloaderFactory {/*** 注册上传下载对象到工厂。** @param upDownloaderName 下载器名称* @return {@link BaseUpDownloader}*/public BaseUpDownloader registerUpDownloader(String upDownloaderName) {if ("tencent".equalsIgnoreCase(upDownloaderName)) {return new TencentUpDownloader();} else if ("ali".equalsIgnoreCase(upDownloaderName)) {return new AliOssUpDownloader();}return null;}
}

4、编写测试方法

/*** 测试工厂模式* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/17*/
public class UpDownloaderFactoryTest {/*** 测试调用阿里上传*/@Testpublic void testAli() {UpDownloaderFactory factory = new UpDownloaderFactory();BaseUpDownloader upDownloader = factory.registerUpDownloader("ali");Map<String, String> param = new HashMap<>();param.put("ossId", "ossId");param.put("token", "token");if (upDownloader == null) {return;}System.out.println("==========上传开始==========");String result = upDownloader.doUpload("/temp/file", "阿里文件.pdf", param);System.out.println("结果:" + result);System.out.println("==========上传结束==========");}/*** 测试调用腾讯上传*/@Testpublic void testTencent() {UpDownloaderFactory factory = new UpDownloaderFactory();BaseUpDownloader upDownloader = factory.registerUpDownloader("tencent");Map<String, String> param = new HashMap<>();param.put("base64", "base64");param.put("appID", "appID");param.put("appSecret", "appSecret");if (upDownloader == null) {return;}System.out.println("==========上传开始==========");String result = upDownloader.doUpload("/temp/file", "腾讯文件.pdf", param);System.out.println("结果:" + result);System.out.println("==========上传结束==========");}}

5、测试结果

①执行testAli方法

==========上传开始==========

ali upload 入参: 阿里文件.pdf ossId token

ali 上传成功!

结果:AliOssUpDownloader upload success

==========上传结束==========

②执行testTencent方法

==========上传开始==========

tencent upload 入参: 腾讯文件.pdf base64 appID appSecret

成功上传到腾讯云

结果:TencentUpDownloader upload success

==========上传结束==========

实现要点

  1. 定义一个用于创建对象的接口或抽象类,让子类决定实例化哪一个类。

    示例中为:BaseUpDownloader

  2. 创建一个工厂类,其中包含一个用于创建产品对象的方法。

    示例中,工厂类为:UpDownloaderFactory;创建产品对象的方法为:registerUpDownloader

  3. 在客户端代码中,通过调用工厂类的方法来创建所需的产品对象,而无需直接调用具体的产品类的构造函数。

    示例中为:

    UpDownloaderFactory factory = new UpDownloaderFactory();

    BaseUpDownloader upDownloader = factory.registerUpDownloader("ali");

总结

本文从模拟需求开始,带着读者一起学习了工厂模式,从上文可知工厂模式其实非常简单,掌握三大实现要点就可以了。所以小七在工作中使用工厂模式的频率也非常的高,但是工厂模式一般是不会单独使用的,他的好伙伴有策略模式、单例模式、模版模式等等,后面小七都会讲到。

本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/320662.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python量化炒股的统计数据图

Python量化炒股的统计数据图 单只股票的收益统计图 查看单只股票的收盘价信息 单击聚宽JoinQuant量化炒股平台中的“策略研究/研究环境”命令&#xff0c;进入Jupyter Notebook的研究平台。然后单击“新建”按钮&#xff0c;创建Python3文件&#xff0c;输入如下代码如下&am…

ComfyUI搭建和注意事项for WIN[笔记]

下载ComfyUI(GitHub - comfyanonymous/ComfyUI: The most powerful and modular stable diffusion GUI, api and backend with a graph/nodes interface.) 从源码上搭建比较麻烦&#xff0c;一般不推荐&#xff0c;所以跑到release里面找一个下载。我的显卡是GeFore GTX 1050 …

STM32编译前置条件配置

本文基于stm32f104系列芯片&#xff0c;记录编程代码前需要的操作&#xff1a; 添加库文件 在ST官网下载标准库STM32F10x_StdPeriph_Lib_V3.5.0&#xff0c;解压后&#xff0c;得到以下界面 启动文件 进入Libraries&#xff0c;然后进入CMSIS&#xff0c;再进入CM3&#xff…

深度学习中的不确定性量化:技术、应用和挑战综述(一)

不确定性量化(UQ)在减少优化和决策过程中的不确定性方面起着关键作用&#xff0c;应用于解决各种现实世界的科学和工程应用。贝叶斯近似和集成学习技术是文献中使用最广泛的两种UQ方法。在这方面&#xff0c;研究人员提出了不同的UQ方法&#xff0c;并测试了它们在各种应用中的…

018、Python+fastapi,第一个Python项目走向第18步:ubuntu24.04 安装cuda和pytorch环境

一、说明 我们安装了pytorch环境之后&#xff0c;会用yolo v9 来测试一下&#xff0c;看8g 显存能不能跑下来&#xff0c;上次用无影云电脑&#xff0c;4cpu8g内存直接爆了&#xff0c;云电脑也死机了&#xff0c;提示一直占用内存不释放&#xff0c;我自己的云电脑不能占用内…

Java中的maven的安装和配置

maven的作用 依赖管理 方便快捷的管理项目依赖的资源&#xff0c;避免版本冲突问题 统一项目管理 提供标准&#xff0c;统一的项目结构 项目构建 标准跨平台&#xff08;Linux、windows、MacOS&#xff09;的自动化项目构建方式 maven的安装和配置 在maven官网下载maven Ma…

【革命启示录】Spring框架:Java开发的“核聚变”能量源!

Hello&#xff0c;我是阿佑&#xff0c;今天给大家整的活是 《Java开发的“核聚变”能量源》 文章目录 Spring框架原理详解一、引言简介目的特点例子 二、背景介绍问题解决方案例子 三、核心概念3.1 控制反转&#xff08;Inversion of Control, IoC&#xff09;定义实现例子与代…

多商户Docker Supervisor进程管理器部署

Dockerfile 根目录下没有Dockerfile的可以复制下面的命令 # 使用基础镜像 FROM leekay0218/crmeb-mer## 复制代码 ## 在本地调试注释掉&#xff0c;使用映射把文件映射进去 #ADD ./ /var/www# 设置工作目录 WORKDIR /var/www# 设置时区为上海 ENV TZAsia/Shanghai RUN ln -sn…

python安装问题及解决办法(pip不是内部或外部命令也不是可运行)

pip是python的包管理工具&#xff0c;使python可在cmd&#xff08;命令行窗口&#xff0c;WinR后输入cmd&#xff09;中执行 针对 “pip不是内部或外部命令也不是可运行” 问题&#xff0c;需要在安装的时候将python添加到环境变量中 上图第三个选项必须勾选才能在cmd中使用pi…

python从0开始学习(四)

目录 前言 1、算数运算符 1.1 //:整除运算符 1.2 %:取模操作 1.3 **&#xff1a;幂运算 2、赋值运算符 3、比较运算符 4、逻辑运算符 5、位运算符 5.1 &&#xff1a;按位与 5.2 |&#xff1a;按位或 5.3 ^&#xff1a;按位异或 5.4 ~&#xff1a;按位取反 5.5…

如何保证Redis双写一致性?

目录 数据不一致问题 数据库和缓存不一致解决方案 1. 先更新缓存&#xff0c;再更新数据 该方案数据不一致的原因 2. 先更新数据库&#xff0c;再更新缓存 3. 先删除缓存&#xff0c;再更新数据库 延时双删 4. 先更新数据库&#xff0c;再删除缓存 该方案数据不一致的…

我独自升级崛起游戏账号登录注册教程 (5.8最新版)

新韩漫公司所发布的这项动作游戏已向玩家们敞开大门&#xff0c;为大家带来了前所未有的游戏体验和乐趣。这个游戏内包含了大量令人着迷的故事、令人印象深刻的战斗场景以及丰富多样的娱乐元素。在这其中最为引人注目的一点就是游戏内容中融入了“虚拟角色”的元素&#xff0c;…

【webrtc】RemoteAudioSource的创建线程

m98 代码&#xff1a;I:\webrtc m98_yjf\src\pc\rtp_transmission_manager.cc RtpTransmissionManager::CreateReceiver 在信令线程创建receiver receiver 是&#xff1a; rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>receiver;其实际…

专家解读 | NIST网络安全框架(1):框架概览

随 着信息技术的快速发展&#xff0c;组织面临着越来越严峻的网络安全挑战。NIST网络安全框架&#xff08;NIST Cybersecurity Framework&#xff0c;CSF&#xff09;是一个灵活的综合性指南&#xff0c;旨在协助各类组织建立、改进和管理网络安全策略&#xff0c;以加强网络安…

【docker 】 push 镜像提示:denied: requested access to the resource is denied

往 Docker Registry &#xff08;私服&#xff09;push 镜像提示&#xff1a;denied: requested access to the resource is denied 镜像push 语法&#xff1a;docker push <registry-host>:<registry-port>/<repository>:<tag> docker push 192.16…

【软件工程】需求分析

目录 前言需求分析需求获取UML概述用例图用例图的组成用例图中的符号和含义包含的两种使用场景 用例图补充&#xff1a;“系统”用例模型建模确定系统参与者确定系统用例 用例文档用例文档组成部分 活动图组成元素初始节点和终点活动节点转换决策与分支、合并分岔与汇合 类图类…

将文本中的unicode字符替换成汉字

背景介绍 msql workbench导出数据库表的数据 导出的json数据 [{"english_id":1, "english_word":"ambition", "homophonic":"am-\u4ffa\uff0cbi-\u5fc5,tion-\u80dc\uff1a\u4ffa\u5fc5\u80dc", "chinese":&quo…

线性表的概念与结构,以及顺序表和链表的简单概念

1.线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的一条直线…

华为 huawei 交换机 配置 MUX VLAN 示例(汇聚层设备)

组网需求 在企业网络中&#xff0c;企业所有员工都可以访问企业的服务器。但对于企业来说&#xff0c;希望企业内部部分员工之间可以互相交流&#xff0c;而部分员工之间是隔离的&#xff0c;不能够互相访问。 如 图 6-4 所示&#xff0c; Switch1 位于网络的汇聚层&#xff0…

C++入门第二节--关键字、命名空间、输入输出

点赞关注不迷路&#xff01;本节涉及c入门关键字、命名空间、输入输出... 1. C关键字 C总计63个关键字&#xff0c;C语言32个关键字 asmdoifreturntrycontinueautodoubleinlineshorttypedefforbooldynamic_castintsignedtypeidpublicbreakelselongsizeoftypenamethrowcaseen…