当前位置: 首页 > news >正文

设计模式-适配器模式-注册器模式

设计模式-适配器模式-注册器模式

适配器模式

如果开发一个搜索中台,需要适配或接入不同的数据源,可能提供的方法参数和平台调用的方法参数不一致,可以使用适配器模式

image-20241129230331103

适配器模式通过封装对象将复杂的转换过程隐藏于幕后。 被封装的对象甚至察觉不到适配器的存在。 例如, 你可以使用一个将所有数据转换为英制单位 (如英尺和英里) 的适配器封装运行于米和千米单位制中的对象。

下面这段代码

postService,userService,imageService分别调用的方法逻辑相同参数不同,可使用接口统一调用

@Component
@Slf4j
public class SearchFacade {@Resourceprivate PostService postService;@Resourceprivate UserService userService;@Resourceprivate ImageService imageService;@ResourceThreadPoolTaskExecutor threadPoolTaskExecutor;public SearchVo searchAll(@RequestBody SearchQueryRequest searchQueryRequest, HttpServletRequest httpServletRequest) {SearchVo searchVo = new SearchVo();if (searchQueryRequest == null) {return searchVo;}String searchText = searchQueryRequest.getSearchText();String searchType = searchQueryRequest.getSearchType();if (StringUtils.isBlank(searchType)) {CompletableFuture<Page<PostVO>> postTask = CompletableFuture.supplyAsync(() -> {PostQueryRequest postQueryRequest = new PostQueryRequest();postQueryRequest.setSearchText(searchText);Page<PostVO> postVOPage = postService.listPostVoPage(postQueryRequest, httpServletRequest);return postVOPage;}, threadPoolTaskExecutor);CompletableFuture<Page<UserVO>> userTask = CompletableFuture.supplyAsync(() -> {UserQueryRequest userQueryRequest = new UserQueryRequest();userQueryRequest.setUserName(searchText);Page<UserVO> userVOPage = userService.listUserVoPage(userQueryRequest);return userVOPage;}, threadPoolTaskExecutor);CompletableFuture<Page<Image>> imageTask = CompletableFuture.supplyAsync(() -> {ImageQueryRequest imageQueryRequest = new ImageQueryRequest();imageQueryRequest.setSearchText(searchText);Page<Image> imagePage = imageService.getImageByPage(imageQueryRequest);return imagePage;}, threadPoolTaskExecutor);CompletableFuture.allOf(postTask, userTask, imageTask);try {Page<PostVO> postVOPage = postTask.get();searchVo.setPostList(postVOPage.getRecords());Page<UserVO> userVOPage = userTask.get();searchVo.setUserList(userVOPage.getRecords());Page<Image> imagePage = imageTask.get();searchVo.setImageList(imagePage.getRecords());} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}} else {SearchTypeEnum searchTypeEnum = SearchTypeEnum.getEnumByValue(searchType);switch (searchTypeEnum) {case POST:PostQueryRequest postQueryRequest = new PostQueryRequest();postQueryRequest.setSearchText(searchText);Page<PostVO> postVOPage = postService.listPostVoPage(postQueryRequest, httpServletRequest);searchVo.setPostList(postVOPage.getRecords());break;case USER:UserQueryRequest userQueryRequest = new UserQueryRequest();userQueryRequest.setUserName(searchText);Page<UserVO> userVOPage = userService.listUserVoPage(userQueryRequest);searchVo.setUserList(userVOPage.getRecords());break;case IMAGE:ImageQueryRequest imageQueryRequest = new ImageQueryRequest();imageQueryRequest.setSearchText(searchText);Page<Image> imagePage = imageService.getImageByPage(imageQueryRequest);searchVo.setImageList(imagePage.getRecords());break;default:break;}}return searchVo;}
}

下面实现一个简单的适配器

新建一个数据源接口

/*** @author tuaofei* @description 查询数据源* @date 2024/11/29*/
public interface SearchDataSource<T> {/*** 通用查询接口* @param searchText* @param current* @param pageSize* @return*/Page<T> doSearch(String searchText, int current, int pageSize);
}

postService.listPostVoPage(postQueryRequest, httpServletRequest)

新增PostDataSource数据源

@Service
@Slf4j
public class PostDataSource implements SearchDataSource<PostVO> {@Resourceprivate PostService postService;@Overridepublic Page<PostVO> doSearch(String searchText, int current, int pageSize) {PostQueryRequest postQueryRequest = new PostQueryRequest();postQueryRequest.setSearchText(searchText);postQueryRequest.setCurrent(current);postQueryRequest.setPageSize(pageSize);//HttpServletRequest 这里没法获取,考虑改造接口或改造方法,根据具体情况判断Page<PostVO> postVOPage = postService.listPostVoPage(postQueryRequest, null);return postVOPage;}
}

新增UserDataSource 数据源

userService.listUserVoPage(userQueryRequest)

@Service
@Slf4j
public class UserDataSource implements SearchDataSource<UserVO> {@Resourceprivate UserService userService;@Overridepublic Page<UserVO> doSearch(String searchText, int current, int pageSize) {UserQueryRequest userQueryRequest = new UserQueryRequest();userQueryRequest.setUserName(searchText);Page<UserVO> userVOPage = userService.listUserVoPage(userQueryRequest);return userVOPage;}
}

新增ImageDataSource 数据源

imageService.getImageByPage(imageQueryRequest)

@Service
public class ImageDataSource implements SearchDataSource<Image> {@Resourceprivate ImageService imageService;@Overridepublic Page<Image> doSearch(String searchText, int current, int pageSize) {ImageQueryRequest imageQueryRequest = new ImageQueryRequest();imageQueryRequest.setSearchText(searchText);imageQueryRequest.setCurrent(current);imageQueryRequest.setPageSize(pageSize);Page<Image> imageByPage = imageService.getImageByPage(imageQueryRequest);return imageByPage;}
}

修改SearchFacade里面调用service的逻辑,这样就可以统一调用相同参数的方法,转换逻辑交给具体的数据源

@Component
@Slf4j
public class SearchFacade {@Resourceprivate ImageDataSource imageDataSource;@Resourceprivate PostDataSource postDataSource;@Resourceprivate UserDataSource userDataSource;@Resourceprivate ThreadPoolTaskExecutor threadPoolTaskExecutor;public SearchVo searchAll(@RequestBody SearchQueryRequest searchQueryRequest, HttpServletRequest httpServletRequest) {SearchVo searchVo = new SearchVo();if (searchQueryRequest == null) {return searchVo;}String searchText = searchQueryRequest.getSearchText();String searchType = searchQueryRequest.getSearchType();int current = searchQueryRequest.getCurrent();int pageSize = searchQueryRequest.getPageSize();if (StringUtils.isBlank(searchType)) {CompletableFuture<Page<PostVO>> postTask = CompletableFuture.supplyAsync(() -> {Page<PostVO> postVOPage = postDataSource.doSearch(searchText, current, pageSize);return postVOPage;}, threadPoolTaskExecutor);CompletableFuture<Page<UserVO>> userTask = CompletableFuture.supplyAsync(() -> {Page<UserVO> userVOPage = userDataSource.doSearch(searchText, current, pageSize);return userVOPage;}, threadPoolTaskExecutor);CompletableFuture<Page<Image>> imageTask = CompletableFuture.supplyAsync(() -> {Page<Image> imagePage = imageDataSource.doSearch(searchText, current, pageSize);return imagePage;}, threadPoolTaskExecutor);CompletableFuture.allOf(postTask, userTask, imageTask);try {Page<PostVO> postVOPage = postTask.get();searchVo.setPostList(postVOPage.getRecords());Page<UserVO> userVOPage = userTask.get();searchVo.setUserList(userVOPage.getRecords());Page<Image> imagePage = imageTask.get();searchVo.setImageList(imagePage.getRecords());} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}} else {SearchTypeEnum searchTypeEnum = SearchTypeEnum.getEnumByValue(searchType);switch (searchTypeEnum) {case POST:Page<PostVO> postVOPage = postDataSource.doSearch(searchText, current, pageSize);;searchVo.setPostList(postVOPage.getRecords());break;case USER:Page<UserVO> userVOPage = userDataSource.doSearch(searchText, current, pageSize);searchVo.setUserList(userVOPage.getRecords());break;case IMAGE:Page<Image> imagePage = imageDataSource.doSearch(searchText, current, pageSize);searchVo.setImageList(imagePage.getRecords());break;default:break;}}return searchVo;}
}

注册器模式

经过上面的修改,我们发现所有的调用查询方法参数都相同,而且都是通过调用实现了SearchDataSource接口的实现类来调用

我们可以简化下面的switch

SearchTypeEnum searchTypeEnum = SearchTypeEnum.getEnumByValue(searchType);switch (searchTypeEnum) {case POST:Page<PostVO> postVOPage = postDataSource.doSearch(searchText, current, pageSize);;searchVo.setPostList(postVOPage.getRecords());break;case USER:Page<UserVO> userVOPage = userDataSource.doSearch(searchText, current, pageSize);searchVo.setUserList(userVOPage.getRecords());break;case IMAGE:Page<Image> imagePage = imageDataSource.doSearch(searchText, current, pageSize);searchVo.setImageList(imagePage.getRecords());break;default:break;}

需要一个Map<String,SearchDataSource>来注册这些数据源,通过类型来获取对应的数据源,再调用查询方法

@Component
public class DataSourceRegistry {@Resourceprivate ImageDataSource imageDataSource;@Resourceprivate PostDataSource postDataSource;@Resourceprivate UserDataSource userDataSource;private Map<String, SearchDataSource<T>> dataSourceMap;/*** 在依赖注入完成后,执行*/@PostConstructpublic void doInit() {dataSourceMap = new HashMap() {{put(SearchTypeEnum.POST.getValue(), postDataSource);put(SearchTypeEnum.USER.getValue(), userDataSource);put(SearchTypeEnum.IMAGE.getValue(), imageDataSource);}};}public SearchDataSource getDataSourceByType(String searchType) {if (dataSourceMap == null) {return null;}return dataSourceMap.get(searchType);}
}

在SearchFacade使用

@Component
@Slf4j
public class SearchFacade {@Resourceprivate DataSourceRegistry dataSourceRegistry;@Resourceprivate ThreadPoolTaskExecutor threadPoolTaskExecutor;public SearchVo searchAll(@RequestBody SearchQueryRequest searchQueryRequest, HttpServletRequest httpServletRequest) {SearchVo searchVo = new SearchVo();if (searchQueryRequest == null) {return searchVo;}String searchText = searchQueryRequest.getSearchText();String searchType = searchQueryRequest.getSearchType();int current = searchQueryRequest.getCurrent();int pageSize = searchQueryRequest.getPageSize();if (StringUtils.isBlank(searchType)) {CompletableFuture<Page<PostVO>> postTask = CompletableFuture.supplyAsync(() -> {SearchDataSource postDataSource = dataSourceRegistry.getDataSourceByType(SearchTypeEnum.POST.getValue());Page<PostVO> postVOPage = postDataSource.doSearch(searchText, current, pageSize);return postVOPage;}, threadPoolTaskExecutor);CompletableFuture<Page<UserVO>> userTask = CompletableFuture.supplyAsync(() -> {SearchDataSource userDataSource = dataSourceRegistry.getDataSourceByType(SearchTypeEnum.USER.getValue());Page<UserVO> userVOPage = userDataSource.doSearch(searchText, current, pageSize);return userVOPage;}, threadPoolTaskExecutor);CompletableFuture<Page<Image>> imageTask = CompletableFuture.supplyAsync(() -> {SearchDataSource imageDataSource = dataSourceRegistry.getDataSourceByType(SearchTypeEnum.IMAGE.getValue());Page<Image> imagePage = imageDataSource.doSearch(searchText, current, pageSize);return imagePage;}, threadPoolTaskExecutor);CompletableFuture.allOf(postTask, userTask, imageTask);try {Page<PostVO> postVOPage = postTask.get();searchVo.setPostList(postVOPage.getRecords());Page<UserVO> userVOPage = userTask.get();searchVo.setUserList(userVOPage.getRecords());Page<Image> imagePage = imageTask.get();searchVo.setImageList(imagePage.getRecords());} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}} else {SearchDataSource<?> dataSource = dataSourceRegistry.getDataSourceByType(searchType);//可以使用公共的返回对象,类型使用泛型Page<?> page = dataSource.doSearch(searchText, current, pageSize);List<?> records = page.getRecords();searchVo.setDataList(records);}return searchVo;}
}

在SearchVo新建公共返回对象

@Data
public class SearchVo implements Serializable {private List<PostVO> postList;private List<Image> imageList;private List<UserVO> userList;/*** 公共返回对象*/private List<?> dataList;
}

相关文章:

设计模式-适配器模式-注册器模式

设计模式-适配器模式-注册器模式 适配器模式 如果开发一个搜索中台&#xff0c;需要适配或接入不同的数据源&#xff0c;可能提供的方法参数和平台调用的方法参数不一致&#xff0c;可以使用适配器模式 适配器模式通过封装对象将复杂的转换过程隐藏于幕后。 被封装的对象甚至…...

减速机润滑油更换的最佳周期是多久?

减速机是工业设备中的重要组成部分&#xff0c;润滑油的使用对于其正常运转和寿命具有至关重要的作用。那么&#xff0c;减速机多久更换一次润滑油呢&#xff1f;实际上&#xff0c;减速机润滑油的更换周期受多种因素影响&#xff0c;以下是一些具体的更换周期建议&#xff1a;…...

程序执行堆栈执行模拟

所有的文件都是在硬盘&#xff08;磁盘&#xff09;上&#xff0c;调用时先调用javac指令的jdk编译成.class然后被java指令的jre送到内存中&#xff0c;java在内存中有自己的一片区域叫JVM&#xff0c;编译进来的文件首先进入方法区。 staitc的属性就是在进入内存的时候开辟了一…...

《Python基础》之数据加密模块hashlib的用法

目录 一、简介 二、用法 步骤一、导入hashlib库 步骤二、创建哈希对象 步骤三、往哈希对象中传值 1、可以在创建对象的时候传值 2、使用updata传值 步骤四、获取经过哈希对象加密后的值 三、注意事项 1、编码问题 2、安全性 3、多次传值 四、总结 一、简介 hashli…...

安装Fcitx5输入框架和输入法自动部署脚本(来自Mark24)-Ubuntu通用

在Ubuntu22.04上安装rime中文输入法的基本教程 上述文章接近废弃。 使用新逻辑配置基本的Fcitx5的输入法。 安装 第一步&#xff0c;下载相关组件 sudo nala install vim sudo nala install ruby sudo nala install fcitx5-rime第二步&#xff0c;设置语言为Fcitx5 而非 默认…...

【IMF靶场渗透】

文章目录 一、基础信息 二、信息收集 三、flag1 四、flag2 五、flag3 六、flag4 七、flag5 八、flag6 一、基础信息 Kali IP&#xff1a;192.168.20.146 靶机IP&#xff1a;192.168.20.147 二、信息收集 Nmap -sP 192.168.20.0/24 Arp-scan -l nmap -sS -sV -p- -…...

Zookeeper选举算法与提案处理概览

共识算法(Consensus Algorithm) 共识算法即在分布式系统中节点达成共识的算法&#xff0c;提高系统在分布式环境下的容错性。 依据系统对故障组件的容错能力可分为&#xff1a; 崩溃容错协议(Crash Fault Tolerant, CFT) : 无恶意行为&#xff0c;如进程崩溃&#xff0c;只要…...

深入了解 Adam 优化器对显存的需求:以 LLaMA-2 7B 模型为例 (中英双语)

中文版 深入了解 Adam 优化器对显存的额外需求&#xff1a;模型参数与优化器状态的显存开销分析 在深度学习模型的训练过程中&#xff0c;显存是一个关键的资源&#xff0c;尤其在处理大型语言模型或深度神经网络时。训练时的显存需求不仅包括模型参数本身&#xff0c;还涉及…...

数据分析学习

数据分析的定义 数据分析是通过对收集到的数据进行清理、转换、建模、分析和解释&#xff0c;从中提取有用的信息和洞察&#xff0c;以帮助做出更好的决策。数据分析可以应用于各种领域&#xff0c;比如商业、金融、医疗、市场营销等&#xff0c;目的是通过数据来发现模式、趋…...

PaddleOCR:一款高性能的OCR工具介绍

一、引言 随着人工智能技术的不断发展&#xff0c;光学字符识别&#xff08;OCR&#xff09;技术在各行各业得到了广泛应用。OCR技术能够将图片、扫描件等非结构化数据中的文字信息提取出来&#xff0c;转换为可编辑的文本格式。在我国&#xff0c;百度开源了一款优秀的OCR工具…...

Transformers快速入门代码解析(一):注意力机制——Attention:Scaled Dot-product Attention

Attention&#xff1a;Scaled Dot-product Attention 引言Scaled Dot-product Attention代码 引言 请注意&#xff01;&#xff01;&#xff01;本博客使用了教程Transformers快速入门中的全部代码&#xff01;&#xff01;&#xff01; 只在我个人理解的基础上为代码添加了注释…...

Git中HEAD、工作树和索引的区别

在Git版本控制系统中&#xff0c;HEAD、工作树&#xff08;Working Tree&#xff09;和索引&#xff08;Index&#xff09;是三个非常重要的概念&#xff0c;它们分别代表了不同的状态或区域&#xff0c;下面我将对这三个概念进行详细的解释。 HEAD 定义&#xff1a;HEAD是一…...

【python量化教程】如何使用必盈API的股票接口,获取最新实时交易数据

实时交易数据简介 股票实时交易数据涵盖股票价格、成交量、涨跌幅等多类信息。其在股票交易中极为关键&#xff0c;高速准确的数据对各方意义重大。投资者可借此及时捕捉机会、优化策略与降低风险&#xff1b;实时准确的实时交易数据是股票市场有效运转的核心要素之一。 使用…...

【C++】动态内存与智能指针——shared_ptr 和 new 结合使用

12.1.3 shared_ptr 和 new 结合使用 如上文所述&#xff0c;如果我们不初始化一个智能指针&#xff0c;那么它将会被初始化为一个空指针&#xff08;需要注意的是&#xff0c;智能指针与普通指针在此处有着非常明显的区别。如果只声明某个类型的普通指针&#xff0c;而不对它进…...

遥感数据集:FTW全球农田边界和对应影像数据,约160万田块边界及7万多个样本

Fields of The World (FTW) 是一个面向农业田地边界实例分割的基准数据集&#xff0c;旨在推动机器学习模型的发展&#xff0c;满足全球农业监测对高精度、可扩展的田地边界数据的需求。该数据集由kerner-lab提供&#xff0c;于2024年8月28日发布&#xff0c;主要特征包括&…...

马斯克的 AI 游戏工作室:人工智能与游戏产业的融合新纪元

近日&#xff0c;马斯克在 X 平台&#xff08;前身为 Twitter&#xff09;发文称&#xff0c;“太多游戏工作室被大型企业所拥有&#xff0c;xAI 将启动一个 AI 游戏工作室&#xff0c;让游戏再次变得精彩”。这一言论不仅展示了马斯克对游戏行业现状的不满&#xff0c;也揭示了…...

URDF(描述机器人模型)和SDF(Gazebo中用于描述仿真环境)

使用URDF&#xff08;Unified Robot Description Format&#xff09; URDF是ROS中用于描述机器人模型的XML格式文件。你可以使用XML文件定义机器人的几何形状、惯性参数、关节和链接等。 示例URDF文件&#xff08;my_robot.urdf&#xff09;&#xff1a; <?xml version&…...

力扣380:O(1)时间插入、删除和获取随机数

实现RandomizedSet 类&#xff1a; RandomizedSet() 初始化 RandomizedSet 对象bool insert(int val) 当元素 val 不存在时&#xff0c;向集合中插入该项&#xff0c;并返回 true &#xff1b;否则&#xff0c;返回 false 。bool remove(int val) 当元素 val 存在时&#xff0…...

【C++boost::asio网络编程】有关socket的创建和连接的笔记

socket的创建和连接 tcp客户端创建端点tcp服务端创建端点创建socket创建TCP 服务器端的 acceptor 套接字创建 acceptor 套接字并绑定客户端连接到服务器通过ip地址解析通过域名解析 服务端接收新连接 tcp客户端创建端点 int client_end_point() {std::string raw_ip_address …...

超级灵感:前端页面功能统一管理方案

前端页面功能统一管理方案 引言 我和朋友聊天想到一个灵感&#xff0c;关于支付状态机管理&#xff0c;这个类可以让我们知道具体上一个状态和下一个状态&#xff0c;这是由于那个事件触发改变&#xff0c;这个功能设计非常好&#xff01; 从而讨论出为什么我们不能把某一个…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...