【原创实现 设计模式】Spring+策略+模版+工厂模式去掉if-else,实现开闭原则,优雅扩展

1 定义与优点

1.1 定义

策略模式(Strategy Pattern)属于对象的⾏为模式。他主要是用于针对同一个抽象行为,在程序运行时根据客户端不同的参数或者上下文,动态的选择不同的具体实现方式,即类的行为可以在运行时更改。
策略模式定义了一系列算法或实现策略,并将每个算法封装在独立的类中,所以对一个策略行为进行修改、添加或者删除策略时不会影响到原有的策略,也就是开闭原则的具体表现。

1.2 优势

  • 方便扩展:使用策略模式可以方便的添加、删除、替换策略,只需要增加策略类即可,不需要修改原有代码
  • 可读性好:不通的策略实现分布在不通的实现类中互不依赖,结构清晰,易于理解。
  • 避免大量的条件判断:使用传统的if-else在分支过多时难以维护,并且不符合开闭原则,增加策略类型时需要增加if-else代码,使用策略模式即可避免这一点。

2 场景与目标

假如你的项目对于文件上传这个业务支持多种具体实现,不仅支持AWS S3、腾讯云 COS、阿里云 OSS,后续还可能接入华为云、Oracle云等云厂商的对象存储。每个待上传的文件都有一个需要上传到哪个对象存储类型的属性,那么对于文件上传有以下的处理步骤:

  • 根据待上传文件信息选择选择不通的对象存储的上传客户端
  • 一些公共的逻辑,比如参数校验,日志记录
    在这里插入图片描述

3 实现

可以使用策略模式+模版方法+工厂模式,并在Spring中进行应用实现。

  • 定义一个文件上传的策略接口
  • 定义一个抽象类实现这个接口,并实现不同对象存储的通用逻辑,定义子类的模版方法
  • 具体不同的对象存储客户端实现抽象类,并实现抽象方法并且定义为一个bean
  • 定义一个工厂管理具体的实现类对象
  • 客户端使用工厂类来获取不同对象存储的具体实现类

具体实现如下:

  1. 定义文件上传的策略接口
public interface CloudStorage {/*** 上传文件** @param uploadPath 上传文件到哪个目录下* @param localFile 待上传的文件*/void upload(String uploadPath, File localFile);}
  1. 定义一个公共的抽象类,所有对象存储都会用到的通用处理逻辑放在这里,然后定义一个doUpload()方法让子类来实现,也即模版方法的具体体现
@Slf4j
public abstract class AbstractCloudStorage implements CloudStorage {/*** 上传文件** @param uploadPath 上传文件到哪个目录下* @param localFile  待上传的文件*/@Overridepublic void upload(String uploadPath, File localFile) {if (StringUtils.isBlank(uploadPath) || Objects.isNull(localFile) || !localFile.exists()) {log.warn("参数异常, uploadPath={}, localFile={}", uploadPath, localFile.getPath());return;}long start = System.currentTimeMillis();doUpload(uploadPath, localFile);log.info("上传完成,耗时:{}ms", (System.currentTimeMillis() - start));}/*** 上传文件** @param uploadPath 上传文件到哪个目录下* @param localFile  待上传的文件*/public abstract void doUpload(String uploadPath, File localFile);
}
  1. 定义不同策略的实现类,增加一种策略只需要增加一个类即可,以达到开放封闭的目的
@Slf4j
@Component
public class CosClient extends AbstractCloudStorage {/*** 上传文件** @param uploadPath 上传文件到哪个目录下* @param localFile 待上传的文件*/@Overridepublic void doUpload(String uploadPath, File localFile) {log.info("Tencent COS 上传文件");}
}@Slf4j
@Component
public class S3Client extends AbstractCloudStorage {/*** 上传文件** @param uploadPath 上传文件到哪个目录下* @param localFile 待上传的文件*/@Overridepublic void doUpload(String uploadPath, File localFile) {log.info("AWS S3 上传文件");}
}
  1. 最后定义一个工厂类,来获取不同类型的对象存储策略的文件上传实例
@Slf4j
@Component
public class CloudStorageClientFactory {@Autowiredprivate Map<String, CloudStorage> cloudStorageMap;/*** 通过对象存储类型获取实际客户端** @param storageType 对象存储类型* @return 对象存储客户端*/public CloudStorage getByType(String storageType) {return cloudStorageMap.get(storageType);}
}

4 客户端调用

通过上面的对策略模式的定义和实现,接下来创建一个上传文件的服务来处理文件上传请求

@Slf4j
@Component
public class FileUploadService {@Autowiredprivate CloudStorageClientFactory cloudStorageClientFactory;/*** 文件上传*/public void fileUpload(FileInfo fileInfo) {// 通过文件需要上传的存储类型获取对应的客户端CloudStorage cloudStorage = cloudStorageClientFactory.getByType(fileInfo.getStorageType());// 执行客户端的文件上传cloudStorage.upload(fileInfo.getUploadPath(), fileInfo.getFile());}
}

通过以上的实现,使用了工厂模式来创建不同类型的对象存储客户端实例,使用策略模式来处理文件上传请求来避免了if-else条件判断,代码简洁易于维护和扩展。
使用模版方法处理了上传文件的公共逻辑,实现了代码优雅复用。这样的实现方式在项目中的实际使用非常频繁。

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

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

相关文章

消息队列设计一个幂等的消费逻辑golang版

如何实现消息幂等 设计幂等的消费逻辑的关键是确保每条消息只被处理一次&#xff0c;即使在网络故障或消费者重启的情况下。通常使用唯一的消息ID和持久化存储来记录处理过的消息ID。 实现步骤 连接kafka和redis检查消息ID处理消息标记消息已处理 package mainimport (&quo…

C# StringBuilder

以下是一些基本的 StringBuilder 使用方法&#xff1a;创建 StringBuilder 实例&#xff1a;追加字符串&#xff1a;插入字符串&#xff1a;删除字符串&#xff1a;替换字符串&#xff1a;清空 StringBuilder&#xff1a;转换 StringBuilder 为字符串&#xff1a;使用容量&…

MySQL1(初始数据库 概念 DDL建库建表 数据库的三大范式 表约束)

目录 一、初始数据库 二、概念 三、DDL建库建表 1. 数据库结构 2. SQL语句分类 3. DDL语句操作数据库 注释&#xff1a; 查看数据库&#xff1a; ​编辑创建数据库&#xff1a; 删除数据库&#xff1a; 选择数据库&#xff1a; 4. 数据库表的字段类型 4.1 字符串…

java将html转成图片

java 将html转成图片 1.导入jar2.代码3.展示结果4.注意事项 最近有一个需求需要根据指定的样式生成图片&#xff0c;使用java原生技术有些麻烦&#xff0c;所以上网搜了下案例&#xff0c;最后发现最好用的还是html2image&#xff0c;这里进行简单总结下。 1.导入jar <!-- 用…

android adb命令常用大全

android adb命令大全 1、取全量日志&#xff1a; adb logcat -v threadtime > 1.log2、dos窗口日志异常&#xff0c;使用命令清理下 adb logcat -G 200M3、直接在dos命令窗口查询某个关键字 adb logcat | findStr "KeyWord"4、查看版本号&#xff1a; adb sh…

腾讯视频VIP会员账号怎么扫码登录一个帐号登录几个人的设备?

腾讯视频VIP会员账号怎么扫码登录&#xff1f; 腾讯视频VIP会员账号要想实现扫码登录&#xff0c;仅支持在电脑Web网页版和WindowsPC软件上登录腾讯视频时&#xff0c;才可以实现手机QQ扫码登录腾讯视频。 腾讯视频VIP与SVIP会员有什么区别&#xff1f; 腾讯视频VIP会员&…

前端小白必学:对Cookie、localStorage 和 sessionStorage 的简单理解

前言 Cookie、localStorage 和 sessionStorage 作为Web开发领域中广泛采用的三种客户端数据存储技术&#xff0c;它们各自拥有独特的优势、应用场景及限制条件&#xff0c;共同支撑起前端数据管理的多样化需求。也是面试常考题之一&#xff0c;今天就和大家简单谈一下我对它们…

Python 量化

当涉及到量化金融和数据分析时&#xff0c;Python是一种非常流行的编程语言&#xff0c;因为它拥有丰富的库和工具&#xff0c;适用于处理金融数据、执行统计分析、制定交易策略等任务。下面是一些常用的Python量化金融模块及其功能的详细介绍&#xff1a; ### 1. **pandas** …

揭开大语言模型(LLM)内部运作的算法逻辑

本文探讨了 Anthropic 的突破性技术&#xff0c;以揭示大型语言模型 (LLM) 的内部工作原理&#xff0c;揭示其不透明的本质。通过深入研究LLM Claude Sonnet 的“大脑”&#xff0c;Anthropic 增强了人工智能的安全性和可解释性&#xff0c;为人工智能的决策过程提供了更深入的…

应用部署方式演变

应用部署方式演变 1.传统部署2.虚拟化部署3.容器化部署 1.传统部署 传统的应用程序部署是将多个应用程序直接部署在操作系统上&#xff0c;一旦其中的某个应用程序出现内存泄漏&#xff0c;那么该程序就会大量吞噬系统内容空间&#xff0c;导致其他应用程序无法正常运行。 2.虚…

如何让两个不同网段的直连地址通信(有点意思)

群里一个朋友出了个题&#xff1a;两个路由器接口直连&#xff0c;一个接口IP是1.1.1.1/30&#xff0c;一个接口IP是2.2.2.2/30&#xff0c;如何让它们通信&#xff1f; 群里的朋友们纷纷献策&#xff1a; 1、用PPP方式连接&#xff0c;直接通 2、配对端IP地址同网段的s…

鱼叉式钓鱼

鱼叉式网络钓鱼&#xff1a; 鱼叉式网络钓鱼是一种网络钓鱼形式&#xff0c;它针对特定个人或组织发送定制消息&#xff0c;旨在引发特定反应&#xff0c;例如泄露敏感信息或安装恶意软件。这些攻击高度个性化&#xff0c;使用从各种来源收集的信息&#xff0c;例如社交媒体资…

Face Adapter - 一键面部表情迁移、换脸工具 本地一键整合包下载

Face Adapter是一款高效的人脸编辑适配器&#xff0c;由浙江大学和腾讯联合开发&#xff0c;适用于预先训练的扩散模型&#xff0c;专门针对人脸再现和交换任务。 只需要上传一张源脸和一张参考人脸&#xff0c;就能按照参考人脸的风格生成相同的面部的表情&#xff0c;一键生…

掌握Python编程的深层技能

一、Python基础语法、变量、列表、字典等运用 1.运行python程序的两种方式 1.交互式即时得到程序的运行结果 2.脚本方式把程序写到文件里(约定俗称文件名后缀为.py),然后用python解释器解释执行其中的内容2.python程序运行的三个步骤 python3.8 C:\a\b\c.py 1.先启动python3…

Golang-channel理解

channel golang-channel语雀笔记整理 channelgolang channel的设计动机&#xff1f;chanel的数据结构/设计思考 golang channel的设计动机&#xff1f; channel是一种不同协程之间实现异步通信的数据结构。golang中有一种很经典的说法是要基于通信实现共享内存&#xff0c;而不…

机器学习基础:开源库学习-Numpy科学计算库

目录 Numpy科学计算库 什么是多维数组 数组基础 高维数组 操作和创建数组 Numpy介绍 创建数组 数组的属性 二维数组 三维数组 数组元素的数据类型 创建特殊的数组 np.arange() np.ones() np.zeros() np.eye() np.linspace() np.logspace() asarray() 数组运…

AUTOSAR汽车电子嵌入式编程精讲300篇-智能网联汽车CAN总线-基于电压信号的CAN总线入侵检测系统设计与实现

目录 前言 入侵检测系统研究现状 入侵检测系统建模 CAN总线 入侵检测威胁模型 Deep SVDD模型 入侵检测系统方案设计 挑战和解决方案 差分信号的采集与处理 差分信号的特征提取 入侵检测模型的设计 入侵检测系统性能评估 实验环境设置 不同的车辆状态 不同数量的…

一致性哈希算法golang版本

什么是一致性哈希 一致性哈希&#xff08;Consistent Hashing&#xff09;是一种分布式系统中常用的算法&#xff0c;用于在节点&#xff08;如缓存服务器&#xff09;之间均匀分配数据。它的核心思想是将所有可能的哈希值组织成一个环形结构&#xff0c;并将数据和节点通过哈…

005 参数绑定处理

文章目录 参数绑定默认支持的参数类型参数绑定使用要求简单类型RequestParam注解 绑定POJO类型绑定集合或者数组类型 参数绑定示例JSP代码Controller代码PO代码 自定义日期参数绑定Converter代码Converter配置 文件类型参数绑定加入依赖包上传页面配置Multipart解析器Controlle…

thymeleaf+mybatis(本文章用于期末考前10分钟速看)

期末速看 pom&#xff08;了解&#xff09;application.propertiessql代码Controller控制层视图service&#xff1a; 服务层mapper&#xff08;dao&#xff09;&#xff1a;持久层entity层(model层&#xff0c;domain层、 bean)&#xff1a;对应数据库表&#xff0c;实体类 效果…