嵌入式开发工程必备的六大设计模式
设计模式是软件开发中前人总结的经典“套路”用于解决特定场景下的代码设计问题。在嵌入式开发中合理使用设计模式能极大提升代码的可维护性、可扩展性和可移植性。但要特别注意嵌入式资源有限ROM/RAM不能生搬硬套比如避免滥用malloc动态内存。下面我结合C语言GD32常用 和嵌入式实战场景为你详解这6种模式。1. 单例模式 (Singleton)**目的**保证一个类结构体在系统中只有一个实例并提供一个全局访问点。**嵌入式场景**管理唯一的硬件资源如系统日志模块、唯一的外设如RTC 或全局配置管理器。C语言实现核心技巧静态局部变量// sys_config.htypedefstruct{intbaud_rate;intsys_tick;}SysConfig_t;// sys_config.cSysConfig_t*GetSysConfig(void){// 静态局部变量存放在静态存储区只会被初始化一次staticSysConfig_t instance{.baud_rate115200,.sys_tick0};returninstance;// 返回统一指针}// 使用任何地方调用 GetSysConfig() 拿到的都是同一个地址GetSysConfig()-baud_rate9600;注意事项在裸机无RTOS下安全在RTOS多任务下若涉及写操作需加互斥锁保护。2. 工厂模式 (Factory)**目的**定义一个用于创建对象结构体的接口让子类/具体模块决定实例化哪一个类。将“创建”和“使用”分离。**嵌入式场景**系统挂载了多个不同型号的传感器如温度传感器有DS18B20、SHT30应用层不需要知道具体型号只需向“工厂”要一个“温度传感器对象”。C语言实现核心技巧函数指针 条件分支// 抽象传感器接口typedefstruct{int(*init)(void);float(*read)(void);}SensorOps_t;// 工厂根据类型号返回具体的操作函数集SensorOps_t*SensorFactory_Create(inttype){staticSensorOps_t ds18b20_ops{DS18B20_Init,DS18B20_Read};staticSensorOps_t sht30_ops{SHT30_Init,SHT30_Read};switch(type){caseTYPE_DS18B20:returnds18b20_ops;caseTYPE_SHT30:returnsht30_ops;default:returnNULL;}}// 应用层使用SensorOps_t*temp_sensorSensorFactory_Create(TYPE_SHT30);temp_sensor-init();floattemptemp_sensor-read();优势新增传感器时只需修改工厂函数上层应用代码init/read调用完全不用改。3. 观察者模式 (Observer)**目的**定义对象间的一对多依赖关系。当一个对象主题状态改变时所有依赖它的对象观察者都会自动收到通知并更新。**嵌入式场景**按键中断触发需要同时通知“LED闪烁模块”、“蜂鸣器模块”和“界面显示模块”。C语言实现核心技巧回调函数链表#defineMAX_OBSERVERS5typedefvoid(*NotifyCallback)(intevent);typedefstruct{NotifyCallback callbacks[MAX_OBSERVERS];intcount;}Subject_t;voidSubject_Attach(Subject_t*sub,NotifyCallback cb){if(sub-countMAX_OBSERVERS)sub-callbacks[sub-count]cb;}voidSubject_Notify(Subject_t*sub,intevent){for(inti0;isub-count;i){sub-callbacks[i](event);// 逐个通知观察者}}// 使用示例Subject_t key_subject;Subject_Attach(key_subject,LED_Blink);Subject_Attach(key_subject,Buzzer_Beep);// 按键中断触发时Subject_Notify(key_subject,KEY_PRESSED);注意观察者模式通常是同步调用的在通知者线程中执行执行时长不能阻塞。4. 状态模式 (State)**目的**允许对象在内部状态改变时改变其行为。将复杂的 if-else / switch-case 状态机解耦把每个状态的行为封装到独立的“状态对象”中。**嵌入式场景**复杂的通信协议握手如TCP状态、菜单导航界面、电源管理运行/休眠/故障。C语言实现核心技巧函数指针表// 定义状态操作接口typedefstructStateMachineStateMachine_t;typedefstruct{void(*handle)(StateMachine_t*machine,intevent);}State_t;// 定义状态机上下文structStateMachine{constState_t*current_state;intdata;};// 具体状态A的handle函数staticvoidStateA_Handle(StateMachine_t*machine,intevent){if(eventEVT_NEXT){printf(State A - State B);machine-current_statestate_b;// 切换状态}}// 使用machine.current_statestate_a;machine.current_state-handle(machine,EVT_NEXT);优势新增“State C”时无需修改旧状态逻辑符合“开闭原则”。5. 发布-订阅模式 (Publish-Subscribe)**目的**这是观察者模式的“进阶解耦版”。发布者Publisher不直接通知订阅者Subscriber而是通过一个中间件消息总线/事件队列 转发。发布者和订阅者完全不知道对方的存在。**嵌入式场景**RTOS环境下的跨任务通信如FreeRTOS的消息队列、GUI框架的事件分发。区别对比重点1观察者模式同步主题持有观察者指针直接调用回调两者耦合在一起。2发布-订阅异步通过中间层队列传递。发布者只管发消息订阅者只管收消息。C语言实现基于RTOS队列// 发布者任务voidTask_Sensor(void*pv){inttempReadTemp();xQueueSend(g_event_queue,temp,0);// 只管发不管谁收}// 订阅者任务1界面voidTask_Display(void*pv){inttemp;while(1){if(xQueueReceive(g_event_queue,temp,portMAX_DELAY)){UpdateLCD(temp);}}}// 订阅者任务2存储voidTask_Storage(void*pv){inttemp;while(1){if(xQueueReceive(g_event_queue,temp,portMAX_DELAY)){SaveToSD(temp);}}}6. 适配器模式 (Adapter)**目的**将一个类的接口转换成客户希望的另一个接口。解决接口不兼容的问题让原本不能一起工作的类可以一起工作。**嵌入式场景**硬件抽象层HAL 的终极体现。例如你的代码原先是基于ST库的 HAL_GPIO_WritePin现在要移植到GD32库的 gpio_bit_write不需要改应用层只需写一个适配器。C语言实现核心技巧中间层封装// 目标接口应用层期望的typedefstruct{void(*write_pin)(uint8_tlevel);}GpioAdapter_t;// 适配器实现将GD32特有的API适配成目标接口staticvoidGD32_WritePin_Impl(uint8_tlevel){// 内部调用GD32原厂库函数gpio_bit_write(GPIOA,GPIO_PIN_8,(bit_status)level);}GpioAdapter_tCreateLedAdapter(void){GpioAdapter_t adapter;adapter.write_pinGD32_WritePin_Impl;returnadapter;}// 应用层永远调用 adapter.write_pin(1)感受不到底层是GD32还是ST。优势这是代码跨平台移植的利器。总结嵌入式开发怎么选设计模式核心价值嵌入式推荐场景资源消耗CPU/RAM单例模式唯一性管理系统配置、日志、唯一外设极低工厂模式创建与使用分离多型号传感器/屏幕驱动抽象低仅函数指针观察者模式同步一对多通知按键触发联动、简单中断分发低维护回调数组状态模式复杂状态逻辑解耦通信协议、菜单、电源管理中需维护多个状态结构体发布-订阅异步完全解耦带RTOS的多任务通信队列较高需RAM做消息队列适配器模式接口转换HAL层移植、老代码适配新库极低纯封装如果你是新手建议优先掌握 适配器模式用来封装外设驱动和 状态模式用来写按键/协议逻辑这两者立竿见影。等项目引入RTOS后发布-订阅消息队列自然就会成为你的主力工具。

相关新闻

嵌入式常用程序架构

嵌入式常用程序架构

常用五种架构并非互斥,更像是一套“组合拳”,分别应对嵌入式开发中不同层面的挑战。下面我将为你逐一介绍它们的核心思想、典型代码体现、适用场景及优缺点。 1. 前后台 状态机架构 这是裸机开发(无操作系统)的终极形态&#xff…

2026/10/18 2:06:56 阅读更多 →
ncmppGui:3分钟掌握网易云音乐NCM格式解密转换技巧

ncmppGui:3分钟掌握网易云音乐NCM格式解密转换技巧

ncmppGui:3分钟掌握网易云音乐NCM格式解密转换技巧 【免费下载链接】ncmppGui 一个使用C编写的极速ncm转换GUI工具 项目地址: https://gitcode.com/gh_mirrors/nc/ncmppGui ncmppGui是一款专为网易云音乐NCM加密格式设计的极速转换工具,采用C编写…

2026/10/18 2:07:18 阅读更多 →
APK Installer:在Windows上直接安装Android应用的完整指南

APK Installer:在Windows上直接安装Android应用的完整指南

APK Installer:在Windows上直接安装Android应用的完整指南 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 你是否曾想在Windows电脑上运行Android应用&…

2026/10/16 5:00:09 阅读更多 →

最新新闻

SteamOS 安装到 AMD 新显卡:RX 9060 XT 性能发挥实战指南

SteamOS 安装到 AMD 新显卡:RX 9060 XT 性能发挥实战指南

最近不少朋友在讨论 SteamOS 装到普通 PC 上的玩法,尤其是搭配 AMD 新卡的组合。有位朋友跟我说,他在一台整机配置并不算高的机器上装好 SteamOS,显卡是 RX 9060 XT,进游戏后的流畅度比想象中要好很多。这里说的“低配”&#xff…

2026/10/18 2:06:55 阅读更多 →
Oracle 11.2.0.1 补丁安装四道生死门与三重验证法

Oracle 11.2.0.1 补丁安装四道生死门与三重验证法

简介:本资源是一份面向Oracle数据库运维工程师与DBA的实战型补丁管理指南,聚焦Oracle 11.2.0.1版本的补丁安装全流程,解决企业环境中常见补丁部署不规范、回滚困难、验证缺失等痛点。文档以清晰步骤覆盖安装前环境检查与全量备份、OPatch工具…

2026/10/18 2:06:55 阅读更多 →
CAD2024安装教程源码:静默安装与彻底卸载脚本实践

CAD2024安装教程源码:静默安装与彻底卸载脚本实践

简介:这份资源面向零基础到进阶的机械设计学习者与工程师,提供CAD2024机械版的下载与安装指引,帮助用户在自己的电脑上顺利部署并运行这款专业计算机辅助设计工具。压缩包共3个文件,以inscode项目配置、html页面和gitignore忽略规…

2026/10/18 2:06:55 阅读更多 →
GrADS气象绘图入门:安装、ctl数据描述与脚本批量出图

GrADS气象绘图入门:安装、ctl数据描述与脚本批量出图

简介:这份资源是面向气象、环境及科研数据分析初学者的GrADS绘图软件入门文档,帮助零基础用户完成软件安装并掌握基本绘图命令。GrADS作为自由软件,支持Windows与Unix平台,可处理经纬度、层次、时间构成的4D格点或离散数据&#x…

2026/10/18 2:06:55 阅读更多 →
加速度传感器能测哪些物理量?从原理到工程选型实测指南

加速度传感器能测哪些物理量?从原理到工程选型实测指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 2:06:55 阅读更多 →
FPGA研发工程师核心技能与学习路径全解析

FPGA研发工程师核心技能与学习路径全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 2:05:55 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →