【原创实现 设计模式】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  待上传的文件
     */
    @Override
    public 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 待上传的文件
     */
    @Override
    public void doUpload(String uploadPath, File localFile) {
        log.info("Tencent COS 上传文件");
    }
}

@Slf4j
@Component
public class S3Client extends AbstractCloudStorage {

    /**
     * 上传文件
     *
     * @param uploadPath 上传文件到哪个目录下
     * @param localFile 待上传的文件
     */
    @Override
    public void doUpload(String uploadPath, File localFile) {
        log.info("AWS S3 上传文件");
    }
}
  1. 最后定义一个工厂类,来获取不同类型的对象存储策略的文件上传实例
@Slf4j
@Component
public class CloudStorageClientFactory {

    @Autowired
    private Map<String, CloudStorage> cloudStorageMap;

    /**
     * 通过对象存储类型获取实际客户端
     *
     * @param storageType 对象存储类型
     * @return 对象存储客户端
     */
    public CloudStorage getByType(String storageType) {
        return cloudStorageMap.get(storageType);
    }
}

4 客户端调用

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

@Slf4j
@Component
public class FileUploadService {

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营第四十七天| 188.买卖股票的最佳时机IV ,309.最佳买卖股票时机含冷冻期 ,714.买卖股票的最佳时机含手续费

188. 买卖股票的最佳时机 IV - 力扣&#xff08;LeetCode&#xff09; class Solution {public int maxProfit(int k, int[] prices) {int[][] dp new int[prices.length][2*k];for(int i0;i<2*k;i){if(i%2 0){dp[0][i] -prices[0];}else{dp[0][i] 0;} }for(int i1;i…

C语言 | Leetcode C语言题解之第206题反转链表

题目&#xff1a; 题解&#xff1a; struct ListNode* reverseList(struct ListNode* head) {if (head NULL || head->next NULL) {return head;}struct ListNode* newHead reverseList(head->next);head->next->next head;head->next NULL;return newHea…

使用Java连接数据库并且执行数据库操作和创建用户登录图形化界面(3)专栏里有上两步的源代码

创建用户登录程序&#xff0c;验证用户账号和密码信息是否在数据库student中的用户表tb_account中存在。用户登录界面如下图所示&#xff1a; 当单击“登录”按钮时&#xff0c;处理以下几种情况&#xff1a; &#xff08;1&#xff09;用户名未输入&#xff0c;提示用户名不能…

Apache Ranger 2.4.0 安装部署

1、安装ranger admin 2、源码编译Ranger wget https://www.apache.org/dist/ranger/2.4.0/apache-ranger-2.4.0.tar.gz tar zxvf apache-ranger-2.4.0.tar.gz cd apache-ranger-2.4.0 mvn -Pall clean mvn clean package -DskipTests maven settting可以设置阿里云进行资源下载…

【漏洞复现】金和OA 未授权访问

【产品介绍】 金和OA协同办公管理系统C6软件&#xff08;简称金和OA&#xff09;&#xff0c;本着简单、适用、高效的原则&#xff0c;贴合企事业单位的实际需求&#xff0c;实行通用化、标准化、智能化、人性化的产品设计&#xff0c;充分体现企事业单位规范管理、提高办公效…

fiddler抓包工具

概念 概念&#xff1a; Fiddler是一个http协议调试代理工具&#xff0c;它能够记录并检查所有你的电脑和互联网之间的http通讯。 http&#xff1a;不加密&#xff0c;端口为80 https&#xff1a;加密&#xff0c;端口为443 原理&#xff1a; 其实就在访问服务器时&#xff0…

Python逻辑控制语句 之 判断语句--if语句的基本结构

1.程序执行的三大流程 顺序 分支&#xff08;判断&#xff09; 循环 2.if 语句的介绍 单独的 if 语句,就是 “如果 条件成⽴,做什么事” 3.if 语句的语法 if 判断条件: 判断条件成立&#xff0c;执行的代码…

reactor网络模型的原理与实现

一、rector网络模型 对高并发编程&#xff0c;网络连接上的消息处理&#xff0c;可以分为两个阶段&#xff1a;等待消息准备好、消息处理。当使用默认的阻塞套接字时&#xff0c;往往是把这两个阶段合而为一&#xff0c;这样操作套接字的代码所在的线程就得睡眠来等待消息准备好…

【工具分享】Nuclei

文章目录 NucleiLinux安装方式Kali安装Windows安装 Nuclei Nuclei 是一款注重于可配置性、可扩展性和易用性的基于模板的快速漏洞验证工具。它使用 Go 语言开发&#xff0c;具有强大的可配置性、可扩展性&#xff0c;并且易于使用。Nuclei 的核心是利用模板&#xff08;表示为简…

【文档智能】DLAFormer:端到端的解决版式分析、阅读顺序方法

前言 前面文章介绍到&#xff0c;文档智能中版式分析(DLA)&#xff08;《【文档智能 & RAG】RAG增强之路&#xff1a;增强PDF解析并结构化技术路线方案及思路》&#xff09;、阅读顺序&#xff08;《【文档智能】符合人类阅读顺序的文档模型-LayoutReader及非官方权重开源…

抖音短视频seo矩阵系统源代码开发系统架构及功能解析

一、矩阵运营系统开发背景: 在数字化经营的浪潮中&#xff0c;抖音开放平台以其独特的影响力和广泛覆盖的用户群体&#xff0c;成为了企业不可忽视的数字营销阵地。然而&#xff0c;企业在享受抖音带来的巨大流量红利的同时&#xff0c;也面临着多账号管理运营协同效率低下、数…

Ollama中文版部署

M1部署Ollama Ollama中文网站: Featured - 精选 - Ollama中文网 下载网址: Download Ollama on macOS 安装后运行llma3模型: ollama run llama3:8b 界面使用: GitHub - open-webui/open-webui: User-friendly WebUI for LLMs (Formerly Ollama WebUI) 部署open-webui: do…

C++知识点总结 (02):C++中的语句(简单语句、条件语句、迭代语句、跳转语句、异常处理语句、try语句等)

文章目录 1、简单语句(1)空语句(2)复合语句 2、条件语句3、迭代语句(1)常规for循环(2)范围for循环(3)while和do...while 4、跳转语句(1)break(2)continue(3)goto 5、异常处理语句(1)标准异常(2)throw抛出异常 6、try语句 1、简单语句 (1)空语句 ; (2)复合语句 用花括号括起来的…

【实施】系统实施方案(软件方案Word)

软件实施方案 二、 项目介绍 三、 项目实施 四、 项目实施计划 五、 人员培训 六、 项目验收 七、 售后服务 八、 项目保障措施 软件开发全套资料获取&#xff1a;私信或者进主页获取。 软件产品&#xff0c;特别是行业解决方案软件产品不同于一般的商品&#xff0c;用户购买软…

JS(JavaScript)二级菜单级联案例演示

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

机器学习原理和代码实现专辑

1. 往期文章推荐 1.【机器学习】图神经网络(NRI)模型原理和运动轨迹预测代码实现 2. 【机器学习】基于Gumbel-Sinkhorn网络的“潜在排列问题”求解 3. 【机器学习】基于Gumbel Top-k松弛技术的图形采样 4. 【机器学习】基于Softmax松弛技术的离散数据采样 5. 【机器学习】正则…

数据仓库建模基础理论-01-为什么需要数据建模?

一、什么是数据模型&#xff1f; 数据模型是数据库的基础结构&#xff0c;用于描述和组织数据的方式。 它不仅是数据库的底层结构&#xff0c;还是一个概念性工具&#xff0c;帮助理解数据的含义和关系。 数据模型包括数据本身、数据之间的关系、数据的语义&#xff08;含义和…

前端面试题(基础篇十三)

一、async 和 defer 的作用是什么&#xff1f;有什么区别&#xff1f; &#xff08;1&#xff09;脚本没有 defer 或 async&#xff0c;浏览器会立即加载并执行指定的脚本&#xff0c;也就是说不等待后续载入的文档元素&#xff0c;读到就加载并执行。 &#xff08;2&#xff0…

第二天:ALOAM前端讲解【第3部分】

(2)面特征 点到面的距离公式: d H = ∣ ( X ~ ( k + 1 , i ) L − X ˉ ( k , j ) L ) ⋅ ( ( X ˉ ( k , j ) L − X ˉ ( k , l ) L ) ( X ˉ ( k , j ) L − X ˉ ( k , m ) L ) ) ∣ ∣ ( X ˉ ( k , j ) L − X ˉ ( k , l ) L ) ( X ˉ ( k , j ) L − X ˉ ( k ,…

Golang | Leetcode Golang题解之第205题同构字符串

题目&#xff1a; 题解&#xff1a; func isIsomorphic(s, t string) bool {s2t : map[byte]byte{}t2s : map[byte]byte{}for i : range s {x, y : s[i], t[i]if s2t[x] > 0 && s2t[x] ! y || t2s[y] > 0 && t2s[y] ! x {return false}s2t[x] yt2s[y] …