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

这是啥设计模式-适配模式

有一个广告召回系统,输入用户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();
}

这个呢,就叫适配器,把其他接口转换成我们想要的接口。

相关文章:

这是啥设计模式-适配模式

有一个广告召回系统&#xff0c;输入用户id就可以给用户推荐相应的广告&#xff0c;一开始我们只有布尔检索和向量检索两种方式。 1. 面向接口编程&#xff0c;而非实现 第一点就是定义接口&#xff0c;客户端关注的是接口&#xff0c;对客户端来说&#xff0c;他只关心检索引…...

大语言模型(LLMs)Tokenizers详解

Tokenizers是大语言模型&#xff08;Large Language Models&#xff0c;LLMs&#xff09;中用于将文本分割成基本单元&#xff08;tokens&#xff09;的工具。这些工具不仅影响模型的输入表示&#xff0c;还直接影响模型的性能和效率。以下是对Tokenizers的详细解释&#xff1a…...

分支-快排/归并---1

目录 1.排序数组 2.数组中的第K个最大元素 3.最小k个数 4.排序数组&#xff08;归并&#xff09; 5.数组中的逆序对 6.计算右侧小于当前元素的个数 7. 翻转对 1.排序数组 快排的写法有很多&#xff0c;这里我采取了相对快的三路划分加随机基准值。 三路划分&#xff0c;是…...

代码随想录训练营 Day32打卡 动态规划 part01 理论基础 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯

代码随想录训练营 Day32打卡 动态规划 part01 一、 理论基础 动态规划中每一个状态一定是由上一个状态推导出来的&#xff0c;这一点就区分于贪心&#xff0c;贪心没有状态推导&#xff0c;而是从局部直接选最优的。 例如&#xff1a;有N件物品和一个最多能背重量为W 的背包…...

【智能流体力学】剖析ANSYS Fluent材料属性设定与边界条件

目录 一、材料属性设定**1. 材料属性的概述****功能****2. 材料属性的类型****标准材料库****多相流****燃烧模型****传热模型****辐射模型****3. 属性设置与函数****4. 自定义材料数据库****5. Granta数据库支持**二、边界条件**1. 通用边界条件****Pressure Inlet (压力-入口…...

微信小程序反编译工具

目录 介绍 工程结构还原 微信开发者工具运行 如何查看当前运行版本? 开启小程序F12 重新打包运行 效果示例 安装 用法 参数说明 获取微信小程序AppID 文件夹名即为AppID 下载地址 介绍 纯Golang实现,一个用于自动化反编译微信小程序的工具,小程序安全利器, 自…...

线程基本概念

一、进程的结束 wait(阻塞) 一般不做额外的事情 wait(非阻塞) 逻辑不受影响&#xff08;必须套在循环中&#xff09; wait作用&#xff1a;1.获取子进程退出状态 2.回收资源 传参为指针&#xff1a;被调修改主调 获取退出状态值&#xff1a; WIFEXITED 判断是否…...

在SpringBoot中执行后台任务

在 Spring Boot 中执行后台任务通常涉及到使用线程池和定时任务。Spring Boot 提供了多种方式来实现后台任务&#xff0c;包括使用 Scheduled 注解、ThreadPoolTaskExecutor 和 ExecutorService。 下面我将详细介绍如何使用这些方法来实现后台任务。 使用 Scheduled 注解 Sp…...

【网络】UDP回显服务器和客户端的构造,以及连接流程

回显服务器&#xff08;Echo Server&#xff09; 最简单的客户端服务器程序&#xff0c;不涉及到业务流程&#xff0c;只是对与 API 的用法做演示 客户端发送什么样的请求&#xff0c;服务器就返回什么样的响应&#xff0c;没有任何业务逻辑&#xff0c;没有进行任何计算或者…...

【智能流体力学】ANSYS Fluent工作流程设置、求解和后处理详解

目录 一、设置阶段1. **模型****功能** :**详细说明及原理** :2. **材料****功能** :**详细说明及原理** :3. **单元区域条件****功能** :**详细说明及原理** :4. **边界条件****功能** :**详细说明及原理** :5. **网格交界面****功能** :**详细说明及原理** :6. **动…...

最新UI六零导航系统源码 | 多模版全开源

六零导航页 (LyLme Spage) 致力于简洁高效无广告的上网导航和搜索入口&#xff0c;支持后台添加链接、自定义搜索引擎&#xff0c;沉淀最具价值链接&#xff0c;全站无商业推广&#xff0c;简约而不简单。 使用PHPMySql&#xff0c;增加后台管理 多模板选择&#xff0c;支持在…...

K8S中使用英伟达GPU —— 筑梦之路

前提条件 根据不同的操作系统&#xff0c;安装好显卡驱动&#xff0c;并能正常识别出来显卡&#xff0c;比如如下截图&#xff1a; GPU容器创建流程 containerd --> containerd-shim--> nvidia-container-runtime --> nvidia-container-runtime-hook --> libnvid…...

2024-2025年最值得选的Java计算机毕业设计选题大全:800个热门选题

一、前言 博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ…...

libnl教程(2):发送请求

文章目录 前言示例示例代码构造请求创建套接字发送请求 简化示例 前言 前置阅读要求&#xff1a;libnl教程(1):订阅内核的netlink广播通知 本文介绍&#xff0c;libnl如何向内核发送请求。这包含三个部分&#xff1a;构建请求&#xff1b;创建套接字&#xff1b;发送请求。 …...

【软件测试】功能测试理论基础

目录 项目的测试流程&#x1f3f4; 需求评审 评审形式 测试人员在需求评审中职责 测试计划与方案 测试计划 问题 测试方案&#x1f3f4; 测试计划与方案的对比 功能测试设计&#x1f3f4; 测试设计的步骤 项目的测试流程&#x1f3f4; 作用&#xff1a; 有序有效开展…...

玩机进阶教程-----回读 备份 导出分区来制作线刷包 回读分区的写入与否 修改xml脚本

很多工作室需要将修改好的系统导出来制作线刷包。前面分享过很多制作线刷包类的教程。那么一个机型中有很多分区。那些分区回读后要写入。那些分区不需要写入。强写有可能会导致不开机 不进系统的故障。首先要明白。就算机型全分区导出后在写回去 都不一定可以开机进系统。那么…...

MongoDB 插入文档

MongoDB 插入文档 MongoDB 是一个流行的 NoSQL 数据库,它使用文档存储数据。在 MongoDB 中,数据以 BSON(Binary JSON)格式存储,这是一种二进制表示的 JSON 格式。MongoDB 提供了灵活的数据模型,使得插入和查询文档变得非常简单。本文将详细介绍如何在 MongoDB 中插入文档…...

【内网】服务器升级nginx1.17.0

今天用rpm包升级内网nginx版本&#xff0c;上来就给我报错 警告&#xff1a;nginx-1.27.0-2.el7.ngx.x86_64.rpm: 头V4 RSA/SHA256 Signature, 密钥 ID 7bd9bf62: NOKEY 错误&#xff1a;依赖检测失败&#xff1a; libcrypto.so.10()(64bit) 被 nginx-1:1.27.0-2.el7.ngx.x…...

歌曲爬虫下载

本次编写一个程序要爬取歌曲音乐榜https://www.onenzb.com/ 里面歌曲。有帮到铁子的可以收藏和关注起来&#xff01;&#xff01;&#xff01;废话不多说直接上代码。 1 必要的包 import requests from lxml import html,etree from bs4 import BeautifulSoup import re impo…...

transformer-explainer

安装和启动 找到这个项目&#xff0c;然后装好了。 这个项目的目的如名字。 https://github.com/poloclub/transformer-explainerTransformer Explained: Learn How LLM Transformer Models Work with Interactive Visualization - poloclub/transformer-explainerhttps:/…...

深入Linux内核链表:从of_property_read_bool看设备树属性的组织与查找

深入Linux内核链表&#xff1a;从of_property_read_bool看设备树属性的组织与查找 在Linux内核开发中&#xff0c;设备树&#xff08;Device Tree&#xff09;作为描述硬件配置的标准方式&#xff0c;其高效解析机制一直是内核开发者关注的焦点。当我们调用 of_property_read_…...

新手也能搞定的Unity 2D像素风游戏:用免费素材包快速搭建你的第一个横版关卡(附JUNGLE RULES风格参考)

零基础打造Unity 2D像素风横版游戏&#xff1a;从素材获取到完整关卡实战指南像素风格游戏近年来持续走红&#xff0c;其独特的复古魅力与相对较低的制作门槛&#xff0c;使其成为独立开发者和新手的理想选择。Unity作为当下最受欢迎的游戏引擎之一&#xff0c;提供了完善的2D开…...

别只当文本框用!解锁Unity InputField的5个隐藏技巧与常见坑点

别只当文本框用&#xff01;解锁Unity InputField的5个隐藏技巧与常见坑点在Unity开发中&#xff0c;InputField组件看似简单&#xff0c;却是用户交互的核心枢纽。很多开发者仅仅把它当作一个基础输入框使用&#xff0c;却不知道其中隐藏着诸多能显著提升用户体验的实用技巧。…...

从原理到操作:彻底搞懂Linux服务器UEFI启动项管理(efibootmgr命令详解)

深入解析Linux服务器UEFI启动管理&#xff1a;efibootmgr命令全攻略当你在Linux服务器上执行efibootmgr命令时&#xff0c;是否曾被那些神秘的Boot000X条目搞得一头雾水&#xff1f;作为现代服务器的主流启动方式&#xff0c;UEFI远比传统的BIOS复杂得多。本文将带你从底层原理…...

【AI问答/前端】前端瞒天过海局(三)

问三&#xff1a;还有一件事&#xff0c;就是浏览器按钮的前进后退&#xff0c;他真实还原了js改前端的过程&#xff0c;就好像真的有过访问纪录&#xff0c;这个是JS纪录下了自己的路由操作历史&#xff0c;改的浏览器地址栏&#xff1f;还是这个路由操作历史真的是写进了浏览…...

2026年横评10款降AI率软件:只选真正管用的那一款!

随着AI写作工具的广泛应用&#xff0c;论文写作和内容创作效率得到了显著提升&#xff0c;许多学生和职场人士都开始依赖这些工具来完成繁重的文字任务。然而&#xff0c;随着各大高校、期刊平台对AIGC内容检测技术的不断升级&#xff0c;AI生成内容的痕迹越来越容易被识别。不…...

哈夫曼树:高效压缩数据的秘密武器

引言在前面的树系列中&#xff0c;我们学习了二叉搜索树、AVL 树和红黑树——它们都是为了高效查找而设计的。今天要讲的哈夫曼树&#xff0c;目的完全不同&#xff1a;它是为了压缩数据而生。哈夫曼树&#xff08;Huffman Tree&#xff09;&#xff0c;又称最优二叉树&#xf…...

为什么你的DeepSeek工具调用总是超时?揭秘底层Tool Executor线程池配置的2个致命默认值及修复代码

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;为什么你的DeepSeek工具调用总是超时&#xff1f;揭秘底层Tool Executor线程池配置的2个致命默认值及修复代码 DeepSeek-R1 模型在调用外部工具&#xff08;如 HTTP API、数据库查询、Python 函数&#xff09;…...

2026中国GEO企业成长路径分析洞察

这份《2026 中国 GEO 企业成长路径分析洞察》由易观分析发布&#xff0c;聚焦生成式引擎优化&#xff08;GEO&#xff09;领域&#xff0c;对比中美差异、拆解本土模式、归纳四类成长路径并给出标杆案例&#xff0c;清晰揭示中国 GEO 行业的底层逻辑、竞争格局与发展方向。关注…...

智能体通信的序列化标准探索:JSON、ProtoBuf与自定义格式的效率之争

智能体通信的「快递员之战」:JSON、ProtoBuf与自定义格式的效率深度探索 关键词 智能体通信、序列化/反序列化、JSON、Protocol Buffers、自定义二进制格式、传输效率、编码效率、跨语言兼容 摘要 在人工智能多智能体系统(Multi-Agent System, MAS)、大语言模型(LLM)驱…...