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

C语言-适配器模式详解与实践

文章目录

  • C语言适配器模式详解与实践
    • 1. 什么是适配器模式?
    • 2. 为什么需要适配器模式?
    • 3. 实际应用场景
    • 4. 代码实现
      • 4.1 UML 关系图
      • 4.2 头文件 (sensor_adapter.h)
      • 4.3 实现文件 (sensor_adapter.c)
      • 4.4 使用示例 (main.c)
    • 5. 代码分析
      • 5.1 关键设计点
      • 5.2 实现特点
    • 6. 编译和运行
    • 7. 注意事项
    • 8. 改进建议
    • 9. 总结
    • 参考资料

C语言适配器模式详解与实践

1. 什么是适配器模式?

适配器模式是一种结构型设计模式,它允许将一个类的接口转换成客户端所期望的另一个接口。适配器让原本由于接口不兼容而不能一起工作的类可以协同工作。

2. 为什么需要适配器模式?

  • 兼容不同接口
  • 复用现有代码
  • 统一接口规范
  • 平滑过渡旧系统
  • 整合第三方库

3. 实际应用场景

  • 传感器数据适配
  • 通信协议转换
  • 接口版本兼容
  • 数据格式转换
  • 驱动程序适配

4. 代码实现

4.1 UML 关系图

NewInterface
+process_data()
OldSystem
+old_process()
Adapter
-old_system
+process_data()

4.2 头文件 (sensor_adapter.h)

#ifndef SENSOR_ADAPTER_H
#define SENSOR_ADAPTER_H#include <stdint.h>// 新接口定义的数据结构
typedef struct {float temperature;float humidity;float pressure;uint32_t timestamp;
} SensorData;// 旧系统的数据结构
typedef struct {int16_t temp_raw;      // 原始温度数据int16_t humi_raw;      // 原始湿度数据int16_t pres_raw;      // 原始气压数据uint32_t time;         // 时间戳
} LegacySensorData;// 新接口
typedef struct {void (*process_data)(const SensorData* data);
} NewInterface;// 旧系统接口
typedef struct {void (*old_process)(const LegacySensorData* data);
} OldSystem;// 适配器
typedef struct {NewInterface interface;OldSystem* old_system;
} SensorAdapter;// 创建适配器
SensorAdapter* create_sensor_adapter(OldSystem* old_system);// 销毁适配器
void destroy_sensor_adapter(SensorAdapter* adapter);// 数据转换函数
SensorData convert_sensor_data(const LegacySensorData* old_data);#endif // SENSOR_ADAPTER_H

4.3 实现文件 (sensor_adapter.c)

#include "sensor_adapter.h"
#include <stdio.h>
#include <stdlib.h>// 数据转换实现
SensorData convert_sensor_data(const LegacySensorData* old_data) {SensorData new_data;// 温度转换 (原始数据除以100得到实际温度)new_data.temperature = old_data->temp_raw / 100.0f;// 湿度转换 (原始数据除以100得到实际湿度)new_data.humidity = old_data->humi_raw / 100.0f;// 气压转换 (原始数据除以10得到实际气压)new_data.pressure = old_data->pres_raw / 10.0f;// 时间戳保持不变new_data.timestamp = old_data->time;return new_data;
}// 适配器的处理函数
static void adapter_process_data(const SensorData* data) {// 将新格式数据转换回旧格式LegacySensorData old_data = {.temp_raw = (int16_t)(data->temperature * 100),.humi_raw = (int16_t)(data->humidity * 100),.pres_raw = (int16_t)(data->pressure * 10),.time = data->timestamp};// 获取适配器实例SensorAdapter* adapter = (SensorAdapter*)((char*)data - offsetof(SensorAdapter, interface));// 调用旧系统的处理函数adapter->old_system->old_process(&old_data);
}// 创建适配器
SensorAdapter* create_sensor_adapter(OldSystem* old_system) {SensorAdapter* adapter = (SensorAdapter*)malloc(sizeof(SensorAdapter));adapter->interface.process_data = adapter_process_data;adapter->old_system = old_system;return adapter;
}// 销毁适配器
void destroy_sensor_adapter(SensorAdapter* adapter) {free(adapter);
}

4.4 使用示例 (main.c)

#include "sensor_adapter.h"
#include <stdio.h>// 旧系统的处理函数
static void legacy_process(const LegacySensorData* data) {printf("旧系统处理数据:\n");printf("原始温度: %d (0.01°C)\n", data->temp_raw);printf("原始湿度: %d (0.01%%)\n", data->humi_raw);printf("原始气压: %d (0.1hPa)\n", data->pres_raw);printf("时间戳: %u\n", data->time);
}// 新系统的处理函数
static void new_process(const SensorData* data) {printf("新系统处理数据:\n");printf("温度: %.2f°C\n", data->temperature);printf("湿度: %.2f%%\n", data->humidity);printf("气压: %.1fhPa\n", data->pressure);printf("时间戳: %u\n", data->timestamp);
}int main() {// 创建旧系统OldSystem old_system = {legacy_process};// 创建适配器SensorAdapter* adapter = create_sensor_adapter(&old_system);// 测试数据LegacySensorData legacy_data = {.temp_raw = 2550,    // 25.50°C.humi_raw = 6000,    // 60.00%.pres_raw = 10150,   // 1015.0hPa.time = 1234567890};printf("=== 测试1:旧数据转换为新格式 ===\n");SensorData new_data = convert_sensor_data(&legacy_data);new_process(&new_data);printf("\n=== 测试2:新接口适配到旧系统 ===\n");adapter->interface.process_data(&new_data);// 清理资源destroy_sensor_adapter(adapter);return 0;
}

5. 代码分析

5.1 关键设计点

  1. 接口转换机制
  2. 数据格式转换
  3. 适配器封装
  4. 向后兼容性

5.2 实现特点

  1. 函数指针实现接口
  2. 数据结构转换
  3. 内存管理安全
  4. 使用简单直观

6. 编译和运行

gcc -c sensor_adapter.c -o sensor_adapter.o
gcc -c main.c -o main.o
gcc sensor_adapter.o main.o -o adapter_demo

7. 注意事项

  1. 数据转换精度
  2. 内存管理
  3. 错误处理
  4. 性能开销

8. 改进建议

  1. 添加错误检查
  2. 支持批量数据
  3. 优化转换效率
  4. 添加数据验证

9. 总结

适配器模式通过转换接口,使得原本不兼容的系统能够协同工作。这种模式特别适合系统升级或整合第三方库的场景。

参考资料

  1. 《设计模式:可复用面向对象软件的基础》
  2. 《C语言程序设计》
  3. 《嵌入式系统设计》

相关文章:

C语言-适配器模式详解与实践

文章目录 C语言适配器模式详解与实践1. 什么是适配器模式&#xff1f;2. 为什么需要适配器模式&#xff1f;3. 实际应用场景4. 代码实现4.1 UML 关系图4.2 头文件 (sensor_adapter.h)4.3 实现文件 (sensor_adapter.c)4.4 使用示例 (main.c) 5. 代码分析5.1 关键设计点5.2 实现特…...

线程的pthread_create、pthread_join、pthread_exit、pthread_detach函数

线程的创建&#xff08;pthread_create&#xff09; pthread_t tid;//本质是unsigned long类型&#xff0c;打印时得到的是该线程的虚拟地址int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void*), void *arg ); pthread_t *thre…...

测试专项4:AI算法测试在测试行业中,该如何定位自己自述

这岗位到底干啥的&#xff1f; 打个比方&#xff1a; 你就像AI模型的“质检员产品经理风险顾问”三合一。 质检员&#xff1a; 别人造了个AI模型&#xff08;比如人脸识别系统&#xff09;&#xff0c;你不能光看它实验室成绩好&#xff0c;得把它丢到现实里折腾&#xff1a;…...

QT-LINUX-Bluetooth蓝牙开发

BlueToothAPI QT-BlueToothApi Qt Bluetooth 6.8.2 官方提供的蓝牙API不支持linux。 D-Bus的API实现蓝牙 确保系统中安装了 BlueZ(版本需≥5.56),并且 Qt 已正确安装并配置了 D-Bus 支持。 默默看了下自己的版本.....D-BUS的API也不支持。 在 D-Bus 中,org 目录是 D-Bus…...

【经验总结】AUTOSAR架构下NvMBlock无效问题分析

目录 前言 正文 1.问题描述 2.问题原因 3.深入分析 3.1NvM_InvalidateNvBlock分析 3.2NvBlock无效后NvM_ReadBlock行为分析 3.3NvBlock无效后NvM_WriteBlock行为分析 4.总结 前言 最近在做所有NvMBlock测试的时候,发现一个NvMBlock始终无法测试成功(写入Block值 --&…...

STM32 的tf卡驱动

基于STM32的TF卡驱动的基本实现步骤和相关代码示例,主要使用SPI接口来与TF卡进行通信。 硬件连接 将TF卡的SPI接口与STM32的SPI引脚连接,通常需要连接SCK(时钟)、MOSI(主出从入)、MISO(主入从出)和CS(片选)引脚。 软件实现 初始化SPI 配置SPI的工作模式、时钟频率…...

stress-ng命令详解

stress-ng 是一款功能强大的 Linux 系统压力测试工具&#xff0c;能够模拟多种复杂负载场景&#xff0c;覆盖 CPU、内存、磁盘 I/O、进程调度等核心资源&#xff0c;帮助开发者验证系统在高负载下的稳定性与性能表现。以下是其核心功能、参数解析及实战案例。 一、工具简介与安…...

【C语言系列】数据在内存中存储

数据在内存中存储 一、整数在内存中的存储二、大小端字节序和字节序判断2.1什么是大小端&#xff1f;2.2练习2.2.1练习12.2.2练习22.2.3练习32.2.4练习42.2.5练习52.2.6练习6 三、浮点数在内存中的存储3.1练习3.2浮点数的存储3.2.1 浮点数存的过程3.2.2 浮点数取的过程 3.3题目…...

【中文翻译】第12章-The Algorithmic Foundations of Differential Privacy

由于GitHub项目仅翻译到前5章&#xff0c;我们从第6章开始通过大语言模型翻译&#xff0c;并导出markdown格式。 大模型难免存在错漏&#xff0c;请读者指正。 教材原文地址&#xff1a;https://www.cis.upenn.edu/~aaroth/Papers/privacybook.pdf 12 其他模型 到目前为止&…...

图解模糊推理过程(超详细步骤)

我们前面已经讨论了三角形、梯形、高斯型、S型、Z型、Π型6种隶属函数&#xff0c;下一步进入模糊推理阶段。 有关六种隶属函数的特点在“Pi型隶属函数&#xff08;Π-shaped Membership Function&#xff09;的详细介绍及python示例”都有详细讲解&#xff1a;https://lzm07.b…...

datawhale组队学习-大语言模型-task5:主流模型架构及新型架构

目录 5.3 主流架构 5.3.1 编码器-解码器架构 5.3.2 因果解码器架构 5.3.3 前缀解码器架构 5.4 长上下文模型 5.4.1 扩展位置编码 5.4.2 调整上下文窗口 5.4.3 长文本数据 5.5 新型模型架构 5.5.1 参数化状态空间模型 5.5.2 状态空间模型变种 5.3 主流架构 在预训…...

为什么后端路由需要携带 /api 作为前缀?前端如何设置基础路径 /api?

一、为什么后端路由需要携带 /api 作为前缀&#xff1f; 1. 区分 API 端点与其他路由 在 Web 应用程序中&#xff0c;后端不仅需要处理 API 请求&#xff0c;还可能需要处理静态资源&#xff08;如 HTML、CSS、JS 文件&#xff09;或其他服务&#xff08;如 WebSocket&#x…...

C++ 关系运算符重载和算术运算符重载的例子,运算符重载必须以operator开头

在C中&#xff0c;运算符重载允许为用户定义的类型&#xff08;类或结构体&#xff09;赋予某些内置运算符的功能。下面是一个关于关系运算符重载&#xff08;&#xff09;和算术运算符重载&#xff08;&#xff09;的简单例子。 示例&#xff1a;复数类的运算符重载 将创建一…...

建造者模式 (Builder Pattern)

建造者模式 (Builder Pattern) 是一种创建型设计模式,它将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。 一、基础 1.1 意图 将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。 1.2 适用场景 当创建复杂对象的算法应该…...

MCU vs SoC

MCU&#xff08;Microcontroller Unit&#xff0c;单片机&#xff09;和SoC&#xff08;System on Chip&#xff0c;片上系统&#xff09;是两种不同的芯片类型&#xff0c;尽管它们都实现了高度集成&#xff0c;但在设计目标、功能复杂性和应用场景上存在显著差异。以下是两者…...

RAG 架构地基工程-Retrieval 模块的系统设计分享

目录 一、知识注入的关键前奏——RAG 系统中的检索综述 &#xff08;一&#xff09;模块定位&#xff1a;连接语言模型与知识世界的桥梁 &#xff08;二&#xff09;核心任务&#xff1a;四大关键问题的协调解法 &#xff08;三&#xff09;系统特征&#xff1a;性能、精度…...

(C语言)习题练习 sizeof 和 strlen

sizeof 上习题&#xff0c;不知道大家发现与上一张的习题在哪里不一样嘛&#xff1f; int main() {char arr[] "abcdef";printf("%zd\n", sizeof(arr));printf("%zd\n", sizeof(arr 0));printf("%zd\n", sizeof(*arr));printf(&…...

Unity Animation的其中一种运用方式

Animation是Unity的旧的动画系统&#xff0c;先说目的&#xff0c;其使用是为了在UI中播放动效&#xff0c;并且在动效播放结束后接自定义事件而设计的 设计的关键点在于&#xff0c;这个脚本不是通过Animation直接播放动画片段&#xff0c;而是通过修改AnimationState的nor…...

湖北楚大夫

品牌出海已成为众多企业拓展业务、提升竞争力的关键战略。楚大夫(chudafu.com)作为一家专注于品牌出海、海外网络营销推广以及外贸独立站搭建的公司&#xff0c;凭借其专业、高效、创新的服务模式&#xff0c;致力于成为中国企业走向国际市场的坚实后盾与得力伙伴。楚大夫通过综…...

框架的CVE漏洞利用 php类 java类 手工操作和自动化操作蓝队分析漏洞利用的流量特征

前言 php重要框架和基本的识别特征 php的主要是 tp框架 和 laravel 当然还有 yii等 tp的主要特征 1\报错信息&#xff1a; 2、图标 3、请求头 Laravel特征 1、报错信息 2、请求头 php框架CVE利用 lavarvel 工具 https://github.com/zhzyker/CVE-2021-3129 https://git…...

前端Wind CSS面试题及参考答案

目录 标准盒模型与 IE 盒模型的区别是什么?如何通过 box-sizing 属性切换这两种盒模型? 如何计算一个元素在标准盒模型下的总宽度(包含 margin、padding、border)? 父元素高度塌陷的原因是什么?请列举至少 3 种清除浮动的方法。 方法一:使用 clear 属性 方法二:使用…...

数据结构 -- 线索二叉树

线索二叉树 线索二叉树的概念 线索二叉树的作用 我们在进行中序遍历时&#xff0c;总是从根节点出发进行二叉树遍历&#xff0c;而当仅知道某一孩子节点的指针时&#xff0c;由于无法访问父节点&#xff0c;所以没有办法进行遍历。由此引入线索二叉树 【思考】①如何找到指定…...

【算法day19】括号生成——数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

括号生成 https://leetcode.cn/problems/generate-parentheses/description/ 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 左括号数必须大于右括号数&#xff0c;且小于等于n class Solution { publ…...

Qt5.15.2实现Qt for WebAssembly与示例

目录 1.什么是Qt for WebAssembly&#xff1f; 1.1 什么是 WebAssembly&#xff1f; 1.2 WebAssembly 的优势 1.3 什么是 Qt for WebAssembly&#xff1f; 1.4 Qt for WebAssembly 的特点 1.5 编译过程 1.6 运行时环境 注意&#xff01;&#xff01;&#xff01;注意&am…...

好吧好吧,看一下达梦的模式与用户的关系

单凭个人感觉&#xff0c;模式在达梦中属于逻辑对象合集&#xff0c;回头再看资料 应该是一个用户可以对应多个模式 问题来了&#xff0c;模式的ID和用户的ID一样吗&#xff1f; 不一样 SELECT USER_ID,USERNAME FROM DBA_USERS WHERE USERNAMETEST1; SELECT ID AS SCHID, NA…...

HOW - DP 动态规划系列(三)(含01背包问题)

目录 一、01背包问题最直接的暴力解法动态规划解法 二、完全背包 通过几个算法的学习&#xff0c;理解和掌握动态规划来解决背包问题。 一、01背包问题 对于面试的话&#xff0c;掌握01背包和完全背包就够用了&#xff0c;最多可以再来一个多重背包。 如果这几种背包分不清&…...

Linux的文件上传下载的lrzsz库的安装与使用

以下是关于 Linux 下 lrzsz 库的安装与使用 的详细指南&#xff0c;适用于通过终端&#xff08;如 SecureCRT、Xshell、MobaXterm 等&#xff09;使用 ZMODEM 协议快速上传和下载文件&#xff1a; 一、lrzsz 简介 功能&#xff1a;提供 rz&#xff08;接收文件&#xff09;和 …...

在linux服务器部署Heygem

前言&#xff1a; Heygem官方文档上提供了基于windwos系统的安装方案。在实际使用过程中个人电脑的配置可能不够。这个时候如果服务器配置够的话&#xff0c;可以尝试在服务器上装一下。但是服务器一般都是linux系统的&#xff0c;于是这篇教程就出现了… 可行性分析 通读安装…...

图书管理系统系统-Java、SpringBoot、Vue和MySQL开发的图书馆管理系统

「springboot、vue图书馆管理系统.zip」 链接&#xff1a;https://pan.quark.cn/s/5a929a7e9450 分享一个图书管理系统&#xff0c;Java、SpringBoot、Vue和MySQL开发的图书馆管理系统 以下是对文本内容的总结&#xff1a; 项目概述 项目名称与背景&#xff1a; 项目概述 项…...

学生管理系统(需求文档)

需求&#xff1a; 采取控制台的方式去书写学生管理系统 分析&#xff1a; 初始菜单&#xff1a; “----------欢迎来到java学生管理系统----------” “1:添加学生” “2&#xff1a;删除学生” “3&#xff1a;修改学生” “4&#xff1a;查询学生” “5&#xff1a;…...