SpringBoot+策略模式实现多种文件存储模式

一、策略模式

背景

针对某种业务可能存在多种实现方式;传统方式是通过传统if…else…或者switch代码判断;

弊端:

  • 代码可读性差
  • 扩展性差
  • 难以维护

策略模式简介

策略模式是一种行为型模式,它将对象和行为分开,将行为定义为一个行为接口和具体行为的实现。

组成:

  • 抽象策略类(Strategy):策略的抽象;
  • 具体策略类(ConcreteStrategy):具体的策略实现,一种具体实现;
  • 环境类(Context):用来操作策略的上下文环境;

二、代码实现

以文件存储方式为例

抽象策略类

package com.qiangesoft.file.core;

import org.springframework.web.multipart.MultipartFile;

/**
 * 文件存储策略接口
 *
 * @author qiangesoft
 * @date 2024-01-06
 */
public interface FileStoreStrategy {

    /**
     * 存储方式
     *
     * @return
     */
    String getType();

    /**
     * 上传文件
     *
     * @param file
     * @return
     * @throws Exception
     */
    void uploadFile(MultipartFile file) throws Exception;
}

具体策略实现

本地存储

package com.qiangesoft.file.core.local;

import com.qiangesoft.file.core.FileStoreStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

/**
 * 文件本地存储
 *
 * @author qiangesoft
 * @date 2024-01-06
 */
@Component
@Slf4j
public class LocalStoreStrategyImpl implements FileStoreStrategy {

    @Override
    public String getType() {
        return "LOCAL";
    }

    @Override
    public void uploadFile(MultipartFile file) throws Exception {
        log.info("upload file by local");
    }
}

minio存储

package com.qiangesoft.file.core.minio;

import com.qiangesoft.file.core.FileStoreStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

/**
 * 文件minio对象存储
 *
 * @author qiangesoft
 * @date 2024-01-06
 */
@Component
@Slf4j
public class MinioStoreStrategyImpl implements FileStoreStrategy {

    @Override
    public String getType() {
        return "MINIO";
    }

    @Override
    public void uploadFile(MultipartFile file) throws Exception {
        log.info("upload file by minio");
    }
}

策略上下文环境

package com.qiangesoft.file.core;

import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 文件存储策略上下文
 *
 * @author qiangesoft
 * @date 2024-01-06
 */
@Component
public class FileStoreStrategyContext {

    /**
     * 策略实现类上下文
     */
    private final Map<String, FileStoreStrategy> strategyMap = new ConcurrentHashMap<>();

    /**
     * 利用Spring的发现机制,将实现了FileStoreStrategy的类都放到strategyMap里面
     */
    public FileStoreStrategyContext(List<FileStoreStrategy> fileStoreStrategyList) {
        for (FileStoreStrategy strategy : fileStoreStrategyList) {
            String type = strategy.getType();
            if (this.strategyMap.containsKey(type)) {
                throw new RuntimeException(String.format("Strategy [%s] is repeat!", type));
            }
            this.strategyMap.put(type, strategy);
        }
    }

    /**
     * 获取具体的策略实现类
     *
     * @param storeType
     * @return
     */
    public FileStoreStrategy getStrategy(String storeType) {
        FileStoreStrategy strategy = strategyMap.get(storeType);
        if (strategy == null) {
            throw new RuntimeException(String.format("Strategy [%s] is not found!", storeType));
        }
        return strategy;
    }
}

调用

package com.qiangesoft.file.demo;

import com.qiangesoft.file.core.FileStoreStrategy;
import com.qiangesoft.file.core.FileStoreStrategyContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Demo
 *
 * @author qiangesoft
 * @date 2024-01-08
 */
@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private FileStoreStrategyContext fileStoreStrategyContext;

    @GetMapping("/upload")
    public String upload(String type) throws Exception {
        FileStoreStrategy fileStoreStrategy = fileStoreStrategyContext.getStrategy(type);
        fileStoreStrategy.uploadFile(null);
        return fileStoreStrategy.getType();
    }

}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

扩展

如果新增一种存储方式,只需增加一个策略实现类,实现FileStoreStrategy接口,重写getType方法,然后再实现具体的业务逻辑;

案例代码

点击下载

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

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

相关文章

PyTorch|view(),改变张量维度

在构建自己的网络时&#xff0c;了解数据经过每个层后的形状变化是必须的&#xff0c;否则&#xff0c;网络大概率会出现问题。PyToch张量有一个方法&#xff0c;叫做view(),使用这个方法&#xff0c;我们可以很容易的对张量的形状进行改变&#xff0c;从而符合网络的输入要求。…

pgAdmin和asdf postgres的安装

安装pgAdmin&#xff1a; curl https://www.pgadmin.org/static/packages_pgadmin_org.pub | sudo apt-key addsudo sh -c echo "deb https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/$(lsb_release -cs) pgadmin4 main" > /etc/apt/sources.list.d/pgadmi…

基于java,spring的汽车租赁系统的设计与实现

1.环境以及简介 基于java,spring的汽车租赁系统的设计与实现&#xff0c;Java项目&#xff0c;SpringBoot项目&#xff0c;vue项目&#xff0c;含开发文档 源码下载 环境配置&#xff1a; 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 …

【Python机器学习】构造决策树

通常来说&#xff0c;构造决策树直到所有叶结点都是纯的叶结点&#xff0c;但这会导致模型非常复杂&#xff0c;并且对于训练数据高度过拟合。 为了防止过拟合&#xff0c;有两种常见策略&#xff1a; 1、尽早停止树的生长&#xff0c;也叫预剪枝 2、先构造树&#xff0c;但…

用友BI组合太适配了,数据分析效果惊人

用友和BI&#xff08;Business Intelligence&#xff0c;商业智能&#xff09;的适配性确实很高&#xff0c;这主要得益于用友在企业管理软件领域的深厚积累和BI在数据分析方面的强大能力。通过将用友的软件与BI工具组合起来&#xff0c;企业可以获得以下几个方面的优势&#x…

年底了,来看看测试大佬的年终项目总结吧!值得借鉴

测试总结&#xff0c;是测试负责人或测试经理的测试管理能力的体现。在项目或版本测试完成&#xff0c;测试报告上交后&#xff0c;测试的工作并不是完结了&#xff0c;而是另外一件大事需要做&#xff0c;那就是为这个项目或是版本做一次测试总结。 添加图片注释&#xff0c;不…

Linux服务器开发太麻烦? 试试IntelliJ IDEA公网远程访问开发极大提升开发效率

文章目录 1. 检查Linux SSH服务2. 本地连接测试3. Linux 安装Cpolar4. 创建远程连接公网地址5. 公网远程连接测试6. 固定连接公网地址7. 固定地址连接测试 本文主要介绍如何在IDEA中设置远程连接服务器开发环境&#xff0c;并结合Cpolar内网穿透工具实现无公网远程连接&#xf…

C语言--结构体详解

C语言--结构体详解 1.结构体产生原因2.结构体声明2.1 结构体的声明2.2 结构体的初始化2.3结构体自引用 3.结构体内存对齐3.1 对齐规则3.2 为什么存在内存对齐3.3 修改默认对⻬数 4. 结构体传参 1.结构体产生原因 C语言将数据类型分为了两种&#xff0c;一种是内置类型&#xf…

径向基函数插值

一、径向基函数的定义 如果 ∣ ∣ x 1 ∣ ∣ ∣ ∣ x 2 ∣ ∣ ||x_1||||x_2|| ∣∣x1​∣∣∣∣x2​∣∣&#xff0c;那么 ϕ ( x 1 ) ϕ ( x 2 ) \phi(x_1)\phi(x_2) ϕ(x1​)ϕ(x2​) 的函数 ϕ \phi ϕ 就是径向函数&#xff0c;即仅由 r ∣ ∣ x ∣ ∣ r||x|| r∣∣…

如何修复 SQL Server 数据库中的恢复挂起状态?

当我们想与关系数据库交互时&#xff0c;SQL 就会出现并帮助用户与数据库进行交互。SQL 从高级语言中获取用户的输入&#xff0c;然后访问将代码转换为机器可理解的形式。SQL 确实会恢复数据库文件&#xff0c;但有时 SQL 服务器恢复暂挂阶段会进入帐户&#xff0c;这会停止恢复…

wordcloud,一个超酷的python库

一、简单介绍一下 词云图是文本挖掘中用来表征词频的数据可视化图像&#xff0c;通过它可以很直观地展现文本数据中地高频词&#xff0c;让读者能够从大量文本数据中快速抓住重点。如下图&#xff1a; wordcloud则是一个非常优秀的词云展示python库&#xff0c;它支持自定义词…

高通开发系列 - toolchain交叉编译器编译kernel以及生成boot镜像

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 返回:专栏总目录 目录 背景概述分析过程generate_defconfig.sh脚本环境准备合并其他几个配置文件开始编译生成dtb镜像

JavaWeb——Spring事务管理

六、Spring事务管理 1. 注解 注解&#xff1a;Transactional 位置&#xff1a;业务&#xff08;service&#xff09;层的方法上、类上、接口上——一般在执行多条增删改方法上加 作用&#xff1a;将当前方法交给spring进行事务管理&#xff0c;方法执行前&#xff0c;开启事…

解决:已经安装open3d,还是报错No module named ‘open3d‘的问题

首先示例&#xff0c;我是如何安装又是如何被报错的过程。 报错过程&#xff1a; 网上普遍的安装指令就是下面这个&#xff1a; pip install open3d 我是直接python页面的终端安装的&#xff1a; 安装完&#xff0c;检查列表已安装文件是否有open3d&#xff0c; 输入指令 …

听GPT 讲Rust源代码--compiler(12)

File: rust/compiler/rustc_data_structures/src/graph/dominators/mod.rs 文件mod.rs位于Rust编译器源代码中的rustc_data_structures/src/graph/dominators目录下。这个文件的作用是实现支配树&#xff08;dominator tree&#xff09;的计算算法。 在编译器优化中&#xff0c…

Hotspot源码解析-第十五章-类加载器初始化前期准备

15.1 ClassLoader初始化 15.1.1 classLoader.cpp 15.1.1.1 classLoader_init void classLoader_init() {ClassLoader::initialize(); }void ClassLoader::initialize() {assert(_package_hash_table NULL, "should have been initialized by now.");EXCEPTION_MA…

Spring学习 Spring整合MyBatis

6.1.创建工程 6.1.1.pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.ap…

3.9 EXERCISES

矩阵加法需要两个输入矩阵A和B&#xff0c;并产生一个输出矩阵C。输出矩阵C的每个元素都是输入矩阵A和B的相应元素的总和&#xff0c;即C[i][j] A[i][j] B[i][j]。为了简单起见&#xff0c;我们将只处理元素为单精度浮点数的平方矩阵。编写一个矩阵加法内核和主机stub函数&am…

C语言详解之一维数组二维数组以及变长数组

一周新的开始&#xff0c;今天的你学习了吗&#xff1f; 前言 今天打算把数组的相关知识知识复习一下&#xff0c;比如初始化&#xff0c;调用&#xff0c;以及他和指针的关系等等 数组是什么 数组是一种数据结构&#xff0c;它由相同类型的元素组成&#xff0c;并按照一定的…

Spring学习 Spring AOP

4.Spring AOP 4.1.为什么要学习AOP? 案例&#xff1a;有一个接口Service有一个addUser方法&#xff0c;在调用addUser(被调用时打印调用前的毫秒数与调用后的毫秒数&#xff09;&#xff0c;其实现为&#xff1a; Service public class UserServiceImpl implements UserServi…