Spring通过注解优雅实现工厂模式

news2024/9/28 13:25:55

Spring通过注解优雅实现工厂模式

工厂模式作为开发者,应该都是耳熟能详的,在课本上、在网络上都会有无数的案例,是一个简单、确十分好用的设计模式。但是实现它的方法有很多,早年见过最多的就是用 if 判断类型,然后返回不同的实现类。后来见过在数据库写上类型和实现类的对应关系,然后通过 getBean 动态获取。

讲实话从个人角度并不推荐这两种实现方式,方案一 :每次新增类型和实现类后还需要去对应工厂类新增映射关系,如果类型太多,看起来也很不优雅;方案二:大多数情况下所谓的灵活都是 伪需求,正常每个类型对应的实现类都是绑死的,一般不会去修改类型和实现类的对应关系,如果将这个关系维护到数据库中,就是为了一个 这辈子都用不上的所谓的灵活,我认为大可不必,这只会对代码阅读 带来更多的障碍。

不优雅的工厂

废话不多说,直接来看看目前见过的比较多的 不优雅 的工厂。

定义接口 DevelopmentEngineerService

public interface DevelopmentEngineerService {
    void writeCode(String codeDesc);
}

定义抽象类 AbstractDevelopmentEngineerService

@Slf4j
@Service
public abstract class AbstractDevelopmentEngineerService implements DevelopmentEngineerService{
    @Override
    public void writeCode(String codeDesc) {
        log.info("{} 实现了{},{}", getLevel(),codeDesc,getResult());
    }
    
    public abstract String getLevel();
    
    public abstract String getResult();

}

多态实现

LowDevelopmentEngineerService

@Service
public class LowDevelopmentEngineerService extends AbstractDevelopmentEngineerService{
    @Override
    public String getLevel() {
        return "初级工程师:花费两天";
    }

    @Override
    public String getResult() {
        return "一堆BUG";
    }
}

MiddleDevelopmentEngineerService

@Service
public class MiddleDevelopmentEngineerService extends AbstractDevelopmentEngineerService{
    @Override
    public String getLevel() {
        return "中级工程师:花费三天";
    }
    
    @Override
    public String getResult() {
        return "成功上线";
    }
}

HighDevelopmentEngineerService

@Service
public class HighDevelopmentEngineerService extends AbstractDevelopmentEngineerService{
    @Override
    public String getLevel() {
        return "高级工程师:让中级工程师花费三天";
    }

    @Override
    public String getResult() {
        return "成功上线";
    }
}

工厂类 FactoryDevelopmentEngineerService

@Service
public class FactoryDevelopmentEngineerService {
    @Autowired
    private LowDevelopmentEngineerService lowDevelopmentEngineerService;
    @Autowired
    private MiddleDevelopmentEngineerService middleDevelopmentEngineerService;
    @Autowired
    private HighDevelopmentEngineerService highDevelopmentEngineerService;

    public DevelopmentEngineerService getDevelopmentEngineerService(String type) {
        if ("low".equals(type)){
            return lowDevelopmentEngineerService;
        } else if ("middle".equals(type)) {
            return middleDevelopmentEngineerService;
        }else if ("high".equals(type)){
            return highDevelopmentEngineerService;
        }else {
            throw new RuntimeException("开发工程师类型异常");
        }
    }
}

测试类与测试结果

public class DevelopmentEngineerServiceTest extends UicServiceApplicationTest {
    @Autowired
    private FactoryDevelopmentEngineerService developmentEngineerService;

    @Test
    public void writeCode(){
        developmentEngineerService.getDevelopmentEngineerService("low").writeCode("用户注册/登录");
        developmentEngineerService.getDevelopmentEngineerService("middle").writeCode("用户注册/登录");
        developmentEngineerService.getDevelopmentEngineerService("high").writeCode("用户注册/登录");
    }
}

在这里插入图片描述

对于以上代码,写的很好,实现了我们需要的功能、也成功的使用了工厂模式,但是我总觉得不够优雅,如果我的类型多达30个,那就要在上面注入30个对象,下面再写上一堆判断?是不是显得代码十分臃肿?

优雅的工厂模式

本质上SpringBoot的便捷和它对的 注解 的应用,是密不可分的。所以我们需要学会如何使用它。以带来更快地开发效率、更简介的代码行,以及看起来更加优雅的实现。

接口和抽象类不变 我就不重复贴代码了

多态实现

LowDevelopmentEngineerService

@Service("low")
public class LowDevelopmentEngineerService extends AbstractDevelopmentEngineerService{
    @Override
    public String getLevel() {
        return "初级工程师:花费两天";
    }

    @Override
    public String getResult() {
        return "一堆BUG";
    }
}

MiddleDevelopmentEngineerService

@Service("middle")
public class MiddleDevelopmentEngineerService extends AbstractDevelopmentEngineerService{
    @Override
    public String getLevel() {
        return "中级工程师:花费三天";
    }
    
    @Override
    public String getResult() {
        return "成功上线";
    }
}

HighDevelopmentEngineerService

@Service("high")
public class HighDevelopmentEngineerService extends AbstractDevelopmentEngineerService{
    @Override
    public String getLevel() {
        return "高级工程师:让中级工程师花费三天";
    }

    @Override
    public String getResult() {
        return "成功上线";
    }
}

注:这里 @Service注解里面有一个 value 属性,而此处则正是利用了这个 value 属性去进行标记

工厂类 FactoryDevelopmentEngineerService

@Service
public class FactoryDevelopmentEngineerService {
    // 根据类型注入 将DevelopmentEngineerService 的所有实现类都注入,map的key 就是 对应service顶部注解的 value 值
    @Autowired
    private Map<String, DevelopmentEngineerService> serviceMap = new ConcurrentHashMap<>();

    public DevelopmentEngineerService getDevelopmentEngineerService(String type) {
        DevelopmentEngineerService service = serviceMap.get(type);
        if (service == null) {
            throw new RuntimeException("开发工程师类型异常");
        }
        return service;
    }
}

通过这种实现方式我们可以确保 实现类和对应类型的映射关系维护在同一个Java 类文件中,并且无论如何新增/修改实现类都不需要再去调整工厂类。代码简介明了。

测试类与测试结果

public class DevelopmentEngineerServiceTest extends UicServiceApplicationTest {
    @Autowired
    private FactoryDevelopmentEngineerService developmentEngineerService;

    @Test
    public void writeCode(){
        developmentEngineerService.getDevelopmentEngineerService("low").writeCode("用户注册/登录");
        developmentEngineerService.getDevelopmentEngineerService("middle").writeCode("用户注册/登录");
        developmentEngineerService.getDevelopmentEngineerService("high").writeCode("用户注册/登录");
    }
}

在这里插入图片描述

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

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

相关文章

Docker部署Minio并配置域名访问

Docker部署Minio并配置域名访问 1、拉取镜像 docker pull minio/minio:RELEASE.2024-08-03T04-33-23Z-cpuv12、启动容器 # 创建数据目录 mkdir /data/minio # 创建配置目录 mkdir /root/.minio # 启动容器(如果不配置域名访问MINIO_BROWSER_URL、MINIO_SERVER_URL可以不用配…

springboot书画在线学习网站-计算机毕业设计源码11849

摘 要 本篇论文旨在设计和开发基于SpringBoot的书画在线学习网站&#xff0c;提供用户便捷的学习方式和丰富的学习资源。在该系统中&#xff0c;用户可以通过网站浏览书画的相关内容&#xff0c;包括诗公告消息、书画资讯、课程信息等。同时&#xff0c;系统还将提供书画的学习…

第七在线联手深服协:以科技之力,绘就时尚 AI 智能商品管理新篇章

7月30日&#xff0c;在深圳&#xff0c;一场堪称行业精英云集、科技锋芒毕露的“科技赋能时尚前沿沙龙”圆满落幕。这场盛会由 7thonline 第七在线与深圳服装行业协会&#xff08;简称“深服协”&#xff09;携手打造&#xff0c;深度聚焦 AI 智能商品管理在时尚天地的创新运用…

Liunx 小程序之进度条

Liunx 小程序之进度条 效果前提条件回车和换行缓冲区倒计时 进度条纯进度条模拟下载的进度条Progressbar.hProgressbar.cmain.cmakefile 效果 先来看效果&#xff0c;这其实是一个动态的进度条&#xff0c;后有源码&#xff0c;运行即可&#xff1a; 前提条件 在制作之前有两…

springboot仓库人力资源管理系统-计算机毕业设计源码45130

摘 要 仓库人力资源管理系统作为一种先进的信息技术工具&#xff0c;在企业中扮演着重要的角色。本文旨在深入探讨SpringBoot仓库人力资源管理系统的各项功能及其优势&#xff0c;以及对企业运营所带来的深远影响。 首先&#xff0c;我们详细探讨了SpringBoot仓库人力资源管理…

Opencv学习-图像变换

1. 图像连接 图像连接是指将两个具有相同高度或者宽度的图像连接在一起&#xff0c;图像的下&#xff08;左&#xff09;边缘是另一个图像的上&#xff08;右&#xff09;边缘。图像连接常在需要对两幅图像内容进行对比或者内容中存在对应信息时显示 对应关系时使用。例如&…

全国十大起名大师排行榜,中国最厉害三个起名大师是谁?

全国十大起名大师排行榜&#xff0c;中国最厉害三个起名大师是谁&#xff1f; 山东济南最受欢迎的起名大师有多位&#xff0c;其中较为知名的包括&#xff1a; ‌颜廷利&#xff0c;被誉为山东济南最出名的起名大师之一&#xff0c;还是现代山东文化名人&#xff0c;通过魔方解…

人工智能时代下,国产服务器操作系统如何加快发展?

人工智能时代下&#xff0c;国产服务器操作系统如何加快发展&#xff1f; 云智融合浪潮下&#xff0c;服务器操作系统产业未来发展将走向何方&#xff1f;英特尔和龙蜥的合作&#xff0c;能为国产操作系统的发展带来什么&#xff1f;双方如何通过合作布局“云AI”时代的未来&am…

配有知识库的AI助手与大模型问答相比,各有哪些优缺点?

1. 配有知识库支持的AI助手 优点&#xff1a; 精确性&#xff1a;知识库是由专业人员整理和维护的&#xff0c;其中的信息通常是经过验证和准确的。因此&#xff0c;配有知识库的AI助手可以提供准确的答案&#xff0c;并且在特定领域的问题上表现良好。可控性&#xff1a;知识…

合并重叠的区间

这一题不能用差分数组&#xff0c;因为 [1 , 4] [5, 6] 这个就会被合并&#xff0c;正确的做法就是先排序 bool cmp(vector<int> a, vector<int> b) {if (a[0] < b[0]) return 1;if (a[0] b[0]) return a[1] < b[1];return 0; } class Solution { public:ve…

Python酷库之旅-第三方库Pandas(065)

目录 一、用法精讲 256、pandas.Series.sparse方法 256-1、语法 256-2、参数 256-3、功能 256-4、返回值 256-5、说明 256-6、用法 256-6-1、数据准备 256-6-2、代码示例 256-6-3、结果输出 257、pandas.DataFrame.sparse方法 257-1、语法 257-2、参数 257-3、功…

分享一个基于人脸识别的小区物业管理系统Spring Boot(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…

我花了一天时间,搭了个专属知识库,部署上线了,手把手教,不信你学不会

自动开了这个号以后&#xff0c;陆陆续续写了很多干货文章&#xff0c;一方面是可以帮助自己梳理思路&#xff0c;另一方面也方便日后查找相关内容。 但是&#xff0c;我想检索某个关键词是在之前哪篇文章写过的&#xff0c;就有点捉急了。CSDN 还好&#xff0c;可以检索到相关…

Python 算法交易实验77 QTV200日常推进-经典策略

说明 最初(去年7月)快快上了一版&#xff0c;到现在差不多正好一年。总体上当时做的还是蛮粗糙的&#xff0c;没有考虑模式&#xff0c;只是简单的用判别模型做了一道。 过去的一年&#xff0c;显然不是特别好的一年。我知道的大部分还是以亏损居多。这版策略竟然没有亏钱&am…

【C++11】:lambda表达式function包装器

目录 前言一&#xff0c;可变参数模板1.1 简单认识1.2 STL容器中的empalce系列相关接口 二&#xff0c;lambda表达式2.1 lambda表达式语法2.2 探索lambda底层 三&#xff0c;包装器3.1 function包装器3.2 bind 四&#xff0c;类的新功能4.1 默认成员函数4.2 关键字default4.3 关…

c++数据保存到.csv文件中,并用opencv离线仿真显示

测试可能不是很方便&#xff0c;希望采集一次数据后期还可以使用&#xff0c;这里提供一个案例&#xff1a; 数据写入fosepose.csv //write.cpp #include <iostream> #include <fstream> #include <iomanip> #include <cstdint> #include <chrono…

达梦数据库的系统视图v$sql_plan

达梦数据库的系统视图v$sql_plan 达梦数据库的V$SQL_PLAN视图主要用于显示缓存中的SQL执行计划信息&#xff0c;在 ini 参数 USE_PLN_POOL !0 时才统计。通过查询这个视图&#xff0c;用户可以获取到缓存中的SQL语句的执行计划&#xff0c;这对于监控和分析数据库中的SQL执行情…

excel去掉小数点前的内容

可以使用"通配符"法 1、去除小数点后的内容 我们按CTRLH&#xff0c;调出查找替换功能 然后在查找内容里面&#xff0c;输入.* 星号是通配符&#xff0c;一点加通配符&#xff0c;表示将小数点后面的任意字符给去掉 2、去除小数点前的内容 我们按CTRLH&#xff0c;调…

Python处理和生成 Word 文档库之python-docx使用详解

概要 在日常工作中,处理和生成 Word 文档是一个常见的需求。Python 提供了一个强大的库 python-docx,使得操作 Word 文档变得简单和高效。python-docx 可以帮助我们创建、修改和读取 Word 文档,适用于各种应用场景,如自动化报告生成、批量文档处理等。本文将详细介绍 pyth…

Spring AOP:面向切面编程的最佳实践 ( 一 )

1.AOP思想 1.1.为什么需要面向切面编程 如果在一个类或者多个类的多个业务逻辑方法中, 在开始,结尾部分包含功能相同的代码称之为横切关注点也叫切面, 这种结构可能符合传统的面向对象编程&#xff08;OOP&#xff09;的封装特性, 但可能导致代码难以维护和扩展。 面向切面编…