这是啥设计模式-适配模式
有一个广告召回系统,输入用户id就可以给用户推荐相应的广告,一开始我们只有布尔检索和向量检索两种方式。
1. 面向接口编程,而非实现
第一点就是定义接口,客户端关注的是接口,对客户端来说,他只关心检索引擎提供出来的接口是什么样子,不在意检索引擎是如何实现的。所以第一点就是抽象出接口。
class Recall {
public:virtual ~Recall() = default;virtual void recall(std::string uid) = 0;
};
2. 实现接口
我们有两个检索引擎,一个倒排,一个向量,根据接口分别实现这两种召回
// 倒排检索
class InvertRecall : public Recall {void recall(std::string uid) override {std::cout << uid << ": invert recall\n";}
};// 向量检索
class VectorRecall : public Recall {void recall(std::string uid) override {std::cout << uid << ": vector recall\n";}
};
3. 客户端调用
我们给客户端提供了两种召回方式,客户端其实并不关心的,他只关心接口是什么,通过这个接口他就可以拿到自己想要的结果
Recall* vectorRecall = new InvertRecall(); // 倒排召回
Recall* invertRecall = new VectorRecall(); // 向量召回
invertRecall->recall(uid);
vectorRecall->recall(uid);
我特意把名字写反了,就是为了表示客户端其实并不关心具体的召回方式是什么,谁来都一样,他只关心recall接口,根据recall接口就可以得到自己想要的结果,我们在改进一下
class AggRecall {
private:std::vector<std::shared_ptr<Recall>> m_recall;
public:void addRecall(const std::shared_ptr<Recall> &recall) {m_recall.emplace_back(recall);}void recall(std::string uid) {for (auto &recall: m_recall) {recall->recall(uid);}}
};
4. 新增了三方接口
除了我们自己实现的两种召回方式,还有一些其他的三方召回方式。当然,人家也很专业,也是面向接口编程,同时提供了一种实现方案。
// 三方代码勿动,以so方式提供
class ThirdPartyRecall {
public:virtual ~ThirdPartyRecall() = default;virtual void process(std::string uid, std::string thirdParty) = 0;
};class ThirdPartyRecallImp : public ThirdPartyRecall {
public:void process(std::string uid, std::string thirdParty) override {std::cout << thirdParty << " recall" << std::endl;}
};
这个时候客户端实现的AggRecall方案就要发生一些变化了,因此三方的接口名字和参数和我们实现的召回接口不一样,一种想当然的方式就是把所有召回引擎的接口统一,大家都叫recall,或者大家都叫process。
5. 统一接口
三方的召回接口是以so的方式提供的,我们想要修改代码也不现实了,一种愚蠢的方法就是修改自己的recall接口,但是你有没有想过,如果又有一个其他三方接口不一致怎么办呢?
// 三方代码勿动,以so方式提供
class GoogleRecall {
public:virtual ~GoogleRecall() = default;virtual void search(std::string uid) = 0;
};class GoogleRecallImp : public GoogleRecall {
public:void search(std::string uid) override {std::cout << uid << ": google search" << std::endl;}
};
6. 适配器
现在的问题就是如何把这些接口统一了,其实很简单,我们把三方的接口包一层不久可以了吗,或者说重命名不就可以了吗
class ThirdPartyAdapter : public Recall {
private:std::shared_ptr<ThirdPartyRecallImp> thirdPartyRecall;
public:explicit ThirdPartyAdapter(std::shared_ptr<ThirdPartyRecallImp> recall) : thirdPartyRecall(std::move(recall)) {}void recall(std::string uid) override {thirdPartyRecall->process(uid, "baidu");}
};
同样可以对其他的三方接口进行转换
class GoogleAdapter : public Recall {
private:std::shared_ptr<GoogleRecallImp> googleRecall;
public:explicit ThirdPartyAdapter(std::shared_ptr<GoogleRecallImp> recall) : googleRecall(std::move(recall)) {}void search(std::string uid) override {googleRecall->search(uid);}
};
就是这么简单,我们把process函数用一个recall函数包装起来,这样客户端在调用的时候依然调用的是recall函数,而且也继承了Recall接口
int main() {auto invertRecall = std::make_shared<InvertRecall>();auto vectorRecall = std::make_shared<VectorRecall>();auto thirdRecall = std::make_shared<ThirdPartyRecallImp>();auto googleRecall = std::make_shared<ThirdPartyAdapter>(thirdRecall);auto aggRecall = std::make_shared<AggRecall>();aggRecall->addRecall(invertRecall);aggRecall->addRecall(vectorRecall);aggRecall->addRecall(googleRecall);aggRecall->doRecall();
}
这个呢,就叫适配器,把其他接口转换成我们想要的接口。
相关文章:
这是啥设计模式-适配模式
有一个广告召回系统,输入用户id就可以给用户推荐相应的广告,一开始我们只有布尔检索和向量检索两种方式。 1. 面向接口编程,而非实现 第一点就是定义接口,客户端关注的是接口,对客户端来说,他只关心检索引…...
大语言模型(LLMs)Tokenizers详解
Tokenizers是大语言模型(Large Language Models,LLMs)中用于将文本分割成基本单元(tokens)的工具。这些工具不仅影响模型的输入表示,还直接影响模型的性能和效率。以下是对Tokenizers的详细解释:…...
分支-快排/归并---1
目录 1.排序数组 2.数组中的第K个最大元素 3.最小k个数 4.排序数组(归并) 5.数组中的逆序对 6.计算右侧小于当前元素的个数 7. 翻转对 1.排序数组 快排的写法有很多,这里我采取了相对快的三路划分加随机基准值。 三路划分,是…...
代码随想录训练营 Day32打卡 动态规划 part01 理论基础 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯
代码随想录训练营 Day32打卡 动态规划 part01 一、 理论基础 动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的。 例如:有N件物品和一个最多能背重量为W 的背包…...
【智能流体力学】剖析ANSYS Fluent材料属性设定与边界条件
目录 一、材料属性设定**1. 材料属性的概述****功能****2. 材料属性的类型****标准材料库****多相流****燃烧模型****传热模型****辐射模型****3. 属性设置与函数****4. 自定义材料数据库****5. Granta数据库支持**二、边界条件**1. 通用边界条件****Pressure Inlet (压力-入口…...
微信小程序反编译工具
目录 介绍 工程结构还原 微信开发者工具运行 如何查看当前运行版本? 开启小程序F12 重新打包运行 效果示例 安装 用法 参数说明 获取微信小程序AppID 文件夹名即为AppID 下载地址 介绍 纯Golang实现,一个用于自动化反编译微信小程序的工具,小程序安全利器, 自…...
线程基本概念
一、进程的结束 wait(阻塞) 一般不做额外的事情 wait(非阻塞) 逻辑不受影响(必须套在循环中) wait作用:1.获取子进程退出状态 2.回收资源 传参为指针:被调修改主调 获取退出状态值: WIFEXITED 判断是否…...
在SpringBoot中执行后台任务
在 Spring Boot 中执行后台任务通常涉及到使用线程池和定时任务。Spring Boot 提供了多种方式来实现后台任务,包括使用 Scheduled 注解、ThreadPoolTaskExecutor 和 ExecutorService。 下面我将详细介绍如何使用这些方法来实现后台任务。 使用 Scheduled 注解 Sp…...
【网络】UDP回显服务器和客户端的构造,以及连接流程
回显服务器(Echo Server) 最简单的客户端服务器程序,不涉及到业务流程,只是对与 API 的用法做演示 客户端发送什么样的请求,服务器就返回什么样的响应,没有任何业务逻辑,没有进行任何计算或者…...
【智能流体力学】ANSYS Fluent工作流程设置、求解和后处理详解
目录 一、设置阶段1. **模型****功能** :**详细说明及原理** :2. **材料****功能** :**详细说明及原理** :3. **单元区域条件****功能** :**详细说明及原理** :4. **边界条件****功能** :**详细说明及原理** :5. **网格交界面****功能** :**详细说明及原理** :6. **动…...
最新UI六零导航系统源码 | 多模版全开源
六零导航页 (LyLme Spage) 致力于简洁高效无广告的上网导航和搜索入口,支持后台添加链接、自定义搜索引擎,沉淀最具价值链接,全站无商业推广,简约而不简单。 使用PHPMySql,增加后台管理 多模板选择,支持在…...
K8S中使用英伟达GPU —— 筑梦之路
前提条件 根据不同的操作系统,安装好显卡驱动,并能正常识别出来显卡,比如如下截图: GPU容器创建流程 containerd --> containerd-shim--> nvidia-container-runtime --> nvidia-container-runtime-hook --> libnvid…...
2024-2025年最值得选的Java计算机毕业设计选题大全:800个热门选题
一、前言 博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ…...
libnl教程(2):发送请求
文章目录 前言示例示例代码构造请求创建套接字发送请求 简化示例 前言 前置阅读要求:libnl教程(1):订阅内核的netlink广播通知 本文介绍,libnl如何向内核发送请求。这包含三个部分:构建请求;创建套接字;发送请求。 …...
【软件测试】功能测试理论基础
目录 项目的测试流程🏴 需求评审 评审形式 测试人员在需求评审中职责 测试计划与方案 测试计划 问题 测试方案🏴 测试计划与方案的对比 功能测试设计🏴 测试设计的步骤 项目的测试流程🏴 作用: 有序有效开展…...
玩机进阶教程-----回读 备份 导出分区来制作线刷包 回读分区的写入与否 修改xml脚本
很多工作室需要将修改好的系统导出来制作线刷包。前面分享过很多制作线刷包类的教程。那么一个机型中有很多分区。那些分区回读后要写入。那些分区不需要写入。强写有可能会导致不开机 不进系统的故障。首先要明白。就算机型全分区导出后在写回去 都不一定可以开机进系统。那么…...
MongoDB 插入文档
MongoDB 插入文档 MongoDB 是一个流行的 NoSQL 数据库,它使用文档存储数据。在 MongoDB 中,数据以 BSON(Binary JSON)格式存储,这是一种二进制表示的 JSON 格式。MongoDB 提供了灵活的数据模型,使得插入和查询文档变得非常简单。本文将详细介绍如何在 MongoDB 中插入文档…...
【内网】服务器升级nginx1.17.0
今天用rpm包升级内网nginx版本,上来就给我报错 警告:nginx-1.27.0-2.el7.ngx.x86_64.rpm: 头V4 RSA/SHA256 Signature, 密钥 ID 7bd9bf62: NOKEY 错误:依赖检测失败: libcrypto.so.10()(64bit) 被 nginx-1:1.27.0-2.el7.ngx.x…...
歌曲爬虫下载
本次编写一个程序要爬取歌曲音乐榜https://www.onenzb.com/ 里面歌曲。有帮到铁子的可以收藏和关注起来!!!废话不多说直接上代码。 1 必要的包 import requests from lxml import html,etree from bs4 import BeautifulSoup import re impo…...
transformer-explainer
安装和启动 找到这个项目,然后装好了。 这个项目的目的如名字。 https://github.com/poloclub/transformer-explainerTransformer Explained: Learn How LLM Transformer Models Work with Interactive Visualization - poloclub/transformer-explainerhttps:/…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
