设计模式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.mzph.cn/bicheng/9566.shtml

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

相关文章

WAGO系统 远程代码执行漏洞复现(CVE-2023-1698)

0x01 产品简介 WAGO是一家专业从事电气互连、自动化和接口电子技术的公司。 0x02 漏洞概述 在 WAGO 的多个产品中,一个漏洞允许未经身份验证的远程攻击者创建新用户并更改设备配置,可导致远程RCE、拒绝服务等使整个系统受损。 0x03 影响范围 751-9301 Compact Controll…

2W,3KVDC隔离 定电压输入,稳压单、双路输出DC-DC模块电源——TPI-2W 系列

TPI-2W系列产品是专门针对PCB上需要与输入电源隔离的电源应用场合而设计的。该产品适用于&#xff1a;1&#xff09;输入电源的电压变化≤5%&#xff1b;2&#xff09;输入输出之间要求隔离电压≥3000VDC&#xff1b;3&#xff09;对输出电压稳定和输出纹波噪声要求高.

达梦数据刷盘测试

达梦数据库为了保证数据故障恢复的一致性&#xff0c;REDO 日志的刷盘必须在数据页刷盘之前进行。 下面我们通过测试来验证是不是这样 执行我们事先准备的SHELL脚本 可以看到第一次strings文件没有输出&#xff0c;说明刚写的数据在数据库的BUFFER缓冲区内&#xff0c;还没有刷…

Screeps工程化之配置化

目录 前言一、抽取配置项二、读取配置项 前言 Screeps中所有代码都会在一个tick&#xff08;游戏内的世间&#xff09;内执行完成&#xff0c;想要做到代码的高度复用&#xff0c;和隔离各个房间creep的行为就需要将部分代码进行配置化&#xff0c;本文仅为作者本人的游戏思路…

机器学习算法 - 逻辑回归

逻辑回归是一种广泛应用于统计学和机器学习领域的回归分析方法&#xff0c;主要用于处理二分类问题。它的目的是找到一个最佳拟合模型来预测一个事件的发生概率。以下是逻辑回归的一些核心要点&#xff1a; 基本概念 输出&#xff1a;逻辑回归模型的输出是一个介于0和1之间的…

翻译《The Old New Thing》 - The performance cost of reading a registry key

The performance cost of reading a registry key - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20060222-11/?p32193 Raymond Chen 2006年2月22日 读取注册表键的性能成本 注册表是一个方便的场所&#xff0c;它以统一且多线程安全的方式…

使用 MSYS2 Qt6 发布绿色版的SDR软件无线电应用

文章目录 概要整体架构流程技术名词解释技术细节在启动器中为子进程设置路径和环境。如何迅速找齐所有的DLL 小结附件 概要 新接触软件定义无线电&#xff08;SDR&#xff09;的朋友一般都会一股脑的安装一些现有的SDR平台。无论是GNURadio还是SDR、SDRSharp、SDRAngel&#x…

C++map和set(个人笔记)

Cmap和set 1.set1.1set的使用1.1.1 set的模板参数列表1.1.2set的构造1.1.3set的迭代器1.1.4 set的容量1.1.5 set修改操作1.1.6 set的具体使用例子 2.map2.1map的使用2.1.1map的模板参数列表2.1.2map的构造2.1.3map的迭代器2.1.4 map的容量与元素访问2.1.5 map中元素的修改2.1.6…

模电·基本共基放大电路

基本共集放大电路 图1.(a)所示为基本共基放大电路&#xff0c;根据放大电路的组成原则&#xff0c;为使晶体管发射结正向偏置且 U B E &#xff1e; U o n {U\tiny BE}&#xff1e;{U\tiny on} UBE&#xff1e;Uon&#xff0c;在其输入回路加电源 V B B V\tiny BB VBB&#xf…

Photoshop中绘图及图像修饰工具的应用

Photoshop中绘图及图像修饰工具的应用 Photoshop中的颜色设置与取样前景色与背景色颜色取样 Photoshop中的颜色替换工具Photoshop中的渐变工具Photoshop中的描边命令Photoshop中的填充工具采用油漆桶进行填充采用填充命令进行填充 Photoshop中的擦除工具 Photoshop中的颜色设置…

SQL子查询练习

学习链接&#xff1a;https://sqlzoo.net/wiki/Window_LAG ● 【题目1】查询在欧洲(Europe)人均gdp大于英国 (United Kingdom)的国家名。人均国内生产总值&#xff08;人均GDP&#xff09;国内生产总值&#xff08;GDP&#xff09;/人口&#xff08;populaiton&#xff09;。…

智能奶柜:健康生活新风尚

智能奶柜&#xff1a;健康生活新风尚 在快节奏的都市生活中&#xff0c;健康与便利成为了现代人的双重追求。而在这两者交汇之处&#xff0c;智能奶柜应运而生&#xff0c;它不仅是科技与生活的完美融合&#xff0c;更是日常营养补给的智慧之选。 清晨的第一缕温暖 —— 新鲜…

pycharm编译器背景设置

最近&#xff0c;瞎逛的时候发现个好玩的&#xff0c;pycharm竟然可以设置背景了&#xff0c;也不知道是不是我太out了&#xff0c;觉得很有意思&#xff0c;略微记录一下 如下步骤&#xff1a; 第五步&#xff1a;选择自己的图片路径 第六步&#xff1a;设置图片透明度&…

【讲解下迭代加深搜索】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

自动驾驶系统中的数据闭环:挑战与前景

目录 自动驾驶概况 1.1自动驾驶分级 1.2自动驾驶国内发展 ​1.3自动驾驶架构模型 数据闭环的意义 2.1 搜集corner case的数据 2.2 提高模型的泛化能力 2.3 驱动算法迭代 数据闭环落地的痛点及对策 3.1 数据采集和使用的合规性问题 3.2 数据确权问题 3.3 数据采集…

Interpreting Super-Resolution Networks with Local Attribution Maps

CVPR2021 问题引入 主要针对的是深度模型的不可解释性&#xff0c;本文使用attribution analysis来分析输入的哪些像素对SR的结果贡献最大&#xff1b;本文提出了Local Attribution Maps&#xff0c;是一种归因方法&#xff0c;延伸了path integral gradient method&#xff…

CLI举例:通过URL分类控制用户访问的网站

华为CLI举例&#xff1a;通过URL分类控制用户访问的网站 配置基于URL分类的URL过滤功能&#xff0c;可以实现对用户访问的某一类网站的控制。既可以是FW自带的预定义分类&#xff0c;也可以是管理员配置的自定义分类。 组网需求 如图1所示&#xff0c;FW作为企业网关部署在网络…

华为OD机试【城市聚集度】(java)(200分)

1、题目描述 一张地图上有N个城市&#xff0c;城市和城市之间有且只有一条道路相连&#xff0c;要么直接相连&#xff0c;要么通过其他城市中转相连(可中转一次或多次)。城市与城市之间的道路都不会成环。 当切断通往某城市i的所有道路后&#xff0c;地图上将分成多个连通的城…

mongoDB分组查询

完整代码 //根据医院编号 和 科室编号 &#xff0c;查询排班规则数据Overridepublic Map<String, Object> getRuleSchedule(long page, long limit, String hoscode, String depcode) {//1 根据医院编号 和 科室编号 查询Criteria criteria Criteria.where("hosco…

云手机:海外舆情监控的新工具

在数字化时代&#xff0c;海外舆情监控对于企业、品牌和政府机构来说&#xff0c;已经变得至关重要。传统的舆情监控方法往往受限于地域、设备和技术&#xff0c;而云手机的出现&#xff0c;为海外舆情监控带来了全新的解决方案。 一、云手机与海外舆情监控的完美结合 云手机作…