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

【嵌入式全套设计模式】吃透4大高频模式:简单工厂/适配器/注册器/策略模式(C语言实战+图解,零基础秒懂)

前言

在嵌入式裸机、RTOS、STM32实际项目开发中,很多开发者习惯直接堆砌大量if-else / switch-case完成业务逻辑。不管是外设驱动管理、多算法切换,还是兼容第三方老旧驱动,无脑硬编码只会导致代码耦合度爆炸、后期维护困难、新增功能牵一发而动全身。

嵌入式开发不需要掌握二十多种设计模式,80%的项目只用到4种核心模式:简单工厂模式、适配器模式、注册器模式、策略模式

本文结合C语言+真实嵌入式硬件场景,搭配架构图解、完整可运行代码、适用场景,一站式吃透全套常用设计模式,帮你写出工业级低耦合、高拓展的插件化代码。

下面我从:核心定义、通俗图解、C语言实战、优缺点、适用场景五大维度,逐一讲解,并文末做全方位对比,彻底帮你区分易混淆的四大模式。

很多嵌入式小伙伴写代码时,都会写大量if-else / switch

比如:传感器滤波、屏幕刷新、通信校验、电机控制,不同模式写一堆判断。

代码又臭又长、耦合极高、新增功能必须修改主逻辑。

今天我给大家详细讲解策略模式(Strategy Pattern),同时一次性帮大家梳理:简单工厂、适配器、注册器、策略模式四大嵌入式最常用设计模式,彻底终结混淆。

一、简单工厂模式(对象创建专用)

1. 核心思想

一句话总结:统一创建对象,上层业务无需手动创建硬件实例。

简单工厂属于创建型设计模式,专门解决【频繁创建同类外设对象】的问题。由一个统一的工厂类/函数,集中管理所有设备的创建过程,上层业务只需要传入设备类型,即可直接获取对应对象,无需接触底层创建细节。

2. 架构图解

整体结构:抽象产品接口→多个具体硬件产品→统一工厂层→上层业务

上层业务层 │ ▼ 【简单工厂层】(switch统一分配创建对象) ┌──────────┬──────────┐ OLED驱动 LCD驱动 TFT驱动

3. 嵌入式实战场景

项目存在OLED、LCD两款屏幕,封装统一初始化、显示接口,由工厂函数根据类型自动创建对应屏幕对象。

4. 完整核心代码

#include <stdio.h> #include <stdlib.h> // 抽象产品:统一屏幕接口 typedef struct Screen{ void (*Init)(void); void (*Show)(const char* str); }Screen; // 具体产品:OLED屏幕 void OLED_Init(void){ printf("OLED屏幕初始化完成\r\n"); } void OLED_Show(const char* str){ printf("OLED显示:%s\r\n",str); } // 具体产品:LCD屏幕 void LCD_Init(void){ printf("LCD屏幕初始化完成\r\n"); } void LCD_Show(const char* str){ printf("LCD显示:%s\r\n",str); } // 设备枚举类型 typedef enum{ SCREEN_OLED, SCREEN_LCD }ScreenType; // 简单工厂:统一创建对象 Screen* Screen_Factory_Create(ScreenType type) { Screen* dev = (Screen*)malloc(sizeof(Screen)); if(dev == NULL) return NULL; switch(type) { case SCREEN_OLED: dev->Init = OLED_Init; dev->Show = OLED_Show; break; case SCREEN_LCD: dev->Init = LCD_Init; dev->Show = LCD_Show; break; default: free(dev);return NULL; } return dev; } // 上层业务调用 int main(void) { Screen* scr = Screen_Factory_Create(SCREEN_OLED); scr->Init(); scr->Show("简单工厂模式"); free(scr); return 0; }

5. 优缺点与适用场景

  • 优点:分离对象创建与业务逻辑,屏蔽硬件底层,上层零感知硬件差异;

  • 缺点:工厂内部依赖switch判断,新增外设必须修改工厂代码,违反开闭原则;

  • 适用场景:外设固定、后期极少新增设备的中小型嵌入式项目。

1. 通俗一句话

同一个功能,多种不同算法,单独封装,动态切换,互不影响。

举个最简单的例子:

  • 目的:去到目的地

  • 策略:走路、骑车、开车、坐地铁

  • 上层不用管怎么实现,随时切换出行方式

2. 解决什么痛点?

消灭超长的 if/else、switch,把不同的算法拆分成独立模块,实现算法与业务解耦

二、适配器模式(接口兼容专用)

1. 核心思想

一句话总结:充当转接转接头,适配接口不兼容的第三方/老旧驱动。

适配器属于结构型设计模式,不负责创建对象、不管理设备,只做一件事:接口翻译与转换。当第三方驱动、老旧硬件的函数名、传参格式和项目自研标准接口不一致时,新增一层适配器做中转,无需修改原有驱动和上层业务。

2. 架构图解

上层业务(只调用标准接口) │ ▼ 【适配器层(接口翻译)】 │ ▼ 老旧/第三方驱动(非标接口)

3. 嵌入式实战场景

项目原有标准屏幕接口为Init/Show,接入一款老旧第三方屏幕驱动,函数接口格式完全不匹配,通过适配器完成兼容适配。

4. 完整核心代码

#include <stdio.h> #include <stdlib.h> #include <string.h> // 系统标准接口 typedef struct Screen{ void (*Init)(void); void (*Show)(const char* str); }Screen; // 第三方老旧非标驱动 void OldScreen_Open(void){ printf("老旧屏幕上电初始化\r\n"); } void OldScreen_Display(const char* msg, int len){ printf("老旧屏幕显示:%s\r\n",msg); } // 适配器:适配老旧驱动 void Adapter_Init(void){ OldScreen_Open(); } void Adapter_Show(const char* str){ OldScreen_Display(str, strlen(str)); } // 创建适配后的标准设备 Screen* Create_Screen_Adapter(void) { Screen* dev = (Screen*)malloc(sizeof(Screen)); dev->Init = Adapter_Init; dev->Show = Adapter_Show; return dev; } // 上层业务调用 int main(void) { Screen* scr = Create_Screen_Adapter(); scr->Init(); scr->Show("适配器模式"); free(scr); return 0; }

5. 优缺点与适用场景

  • 优点:隔离非标驱动,上层业务零改动即可兼容第三方组件;

  • 缺点:增加一层中间层,轻微增加代码量;

  • 适用场景:对接老旧驱动、第三方库、开源外设驱动。

  1. 抽象策略:统一函数接口(C语言用函数指针结构体)

  2. 具体策略:每一种算法单独实现

  3. 上下文Context:统一调用入口,用来动态绑定/切换策略

三、注册器模式(设备管理专用,升级版工厂)

1. 核心思想

一句话总结:设备自主注册、全局表格管理、上层查表调用,彻底消灭switch。

注册器是嵌入式工程最常用的进阶模式,属于改良版创建型模式。摒弃简单工厂的switch硬编码,维护一张全局注册表;所有外设驱动初始化时主动注册到表格,上层通过设备名称/ID查表获取对象,完美符合开闭原则。

2. 架构图解

上层业务层(查表调用) │ ▼ 【全局注册器注册表】 ┌───────┬───────┬───────┐ OLED(已注册) LCD(已注册) 其他外设

3. 嵌入式实战场景

管理多款屏幕外设,所有屏幕自主注册到注册表,上层通过设备名称直接查找使用,新增外设无需修改注册器源码。

4. 完整核心代码

#include <stdio.h> #include <stdlib.h> #include <string.h> #define DEV_MAX_NUM 16 // 统一屏幕接口 typedef struct Screen{ const char* name; void (*Init)(void); void (*Show)(const char* str); }Screen; // 全局注册表 static Screen* g_ScreenReg[DEV_MAX_NUM]; static int g_DevCnt = 0; // 注册设备 int Screen_Register(Screen* dev) { if(g_DevCnt >= DEV_MAX_NUM || dev == NULL) return -1; g_ScreenReg[g_DevCnt++] = dev; return 0; } // 按名称查找设备 Screen* Screen_Find(const char* name) { for(int i=0;i<g_DevCnt;i++) { if(strcmp(g_ScreenReg[i]->name,name) == 0) return g_ScreenReg[i]; } return NULL; } // 定义OLED设备并实现功能 void OLED_Init(void){ printf("OLED初始化\r\n"); } void OLED_Show(const char* str){ printf("OLED:%s\r\n",str); } Screen oled_dev = {"OLED",OLED_Init,OLED_Show}; // 定义LCD设备并实现功能 void LCD_Init(void){ printf("LCD初始化\r\n"); } void LCD_Show(const char* str){ printf("LCD:%s\r\n",str); } Screen lcd_dev = {"LCD",LCD_Init,LCD_Show}; // 统一注册入口 void Screen_Module_Init(void) { Screen_Register(&oled_dev); Screen_Register(&lcd_dev); } // 上层业务 int main(void) { Screen_Module_Init(); Screen* scr = Screen_Find("OLED"); scr->Init(); scr->Show("注册器模式"); return 0; }

5. 优缺点与适用场景

  • 优点:彻底消灭switch,新增外设无需修改核心代码,插件化拓展;

  • 缺点:需要维护全局注册表,占用少量内存;

  • 适用场景:多外设管理、插件化架构、后期频繁新增硬件的中大型项目。

1. 业务场景

我们的屏幕拥有三种刷新模式:

  • 正常全屏刷新:画质高、速度慢

  • 局部区域刷新:只更新变动区域,节省性能

  • 高速刷屏模式:舍弃画质,极致提速

我们需要在程序运行过程中随时动态切换刷新策略

2. 完整可运行代码

#include <stdio.h> #include <stdlib.h> // ===================== 1.抽象策略:统一刷新接口 ===================== typedef struct RefreshStrategy { // 刷新算法接口 void (*refresh)(void); }RefreshStrategy; // ===================== 2.具体策略:三种刷新算法 ===================== // 策略1:全屏正常刷新 void Normal_Refresh(void) { printf("【策略1】执行全屏正常刷新,画质优先\r\n"); } // 策略2:局部区域刷新 void Part_Refresh(void) { printf("【策略2】执行局部区域刷新,性能均衡\r\n"); } // 策略3:高速刷屏刷新 void Fast_Refresh(void) { printf("【策略3】执行高速刷屏模式,速度优先\r\n"); } // ===================== 3.上下文:统一调用管理层 ===================== typedef struct { RefreshStrategy* strategy; }Context; // 设置当前策略(动态切换) void Set_Context_Strategy(Context* ctx, RefreshStrategy* s) { if(ctx == NULL || s == NULL) return; ctx->strategy = s; } // 执行当前绑定的策略 void Context_Run(Context* ctx) { if(ctx != NULL && ctx->strategy->refresh != NULL) { ctx->strategy->refresh(); } } // ===================== 上层业务测试 ===================== int main(void) { // 定义三种策略对象 RefreshStrategy s1 = {Normal_Refresh}; RefreshStrategy s2 = {Part_Refresh}; RefreshStrategy s3 = {Fast_Refresh}; Context screenCtx; // 切换为正常刷新 Set_Context_Strategy(&screenCtx, &s1); Context_Run(&screenCtx); // 切换为局部刷新 Set_Context_Strategy(&screenCtx, &s2); Context_Run(&screenCtx); // 切换为高速刷屏 Set_Context_Strategy(&screenCtx, &s3); Context_Run(&screenCtx); return 0; }

3. 运行结果

【策略1】执行全屏正常刷新,画质优先 【策略2】执行局部区域刷新,性能均衡 【策略3】执行高速刷屏模式,速度优先

四、策略模式(算法切换专用)

1. 核心思想

一句话总结:同一功能、多种算法,独立封装,运行时动态切换。

策略模式属于行为型设计模式,和前面三种模式定位完全不同:它不管理设备、不创建对象、不适配接口,专门用于解决同一功能下多种算法逻辑切换的问题,替代业务层大量的if-else判断。

2. 架构图解

上层业务层 │ ▼ 【上下文Context(绑定策略)】 │ ┌───────┬───────┬───────┐ 全屏刷新 局部刷新 高速刷新(不同策略算法)

3. 嵌入式实战场景

屏幕刷新功能,封装全屏刷新、局部刷新、高速刷屏三种算法,程序运行中可自由切换刷新策略。

4. 完整可运行代码

策略模式在裸机、RTOS、Linux嵌入式项目中使用频率极高:

  1. 滤波算法:均值滤波、中值滤波、卡尔曼滤波动态切换

  2. 通信校验:和校验、CRC8、CRC16、CRC32 多种校验算法

  3. 屏幕显示:全屏刷新、局部刷新、动画刷新

  4. 电机控制:PID控制、BangBang控制、模糊控制

  5. 数据加密:不同加密/解码策略自由切换

四、策略模式优缺点

优点

  • 彻底消灭臃肿的 if/switch 判断

  • 算法互相独立,互不干扰,方便单独调试

  • 运行时动态切换策略,灵活性拉满

  • 新增算法无需修改上层代码,符合开闭原则

缺点

  • 每一种策略都需要新增结构体与函数,项目文件会变多

  • 对新手来说,前期理解成本比直接写if高

五、四大设计模式全方位对比(嵌入式必背)

1. 核心定位区别

设计模式

所属类型

核心职责

通俗口诀

解决问题

简单工厂

创建型

统一创建外设对象

我帮你造对象

分散的对象创建逻辑

适配器

结构型

兼容非标硬件接口

我帮你改接口

驱动接口不匹配

注册器

创建型(进阶)

插件化管理所有外设

你来报名我管理

工厂switch臃肿、拓展性差

策略模式

行为型

动态切换业务算法

多种算法随便换

业务层大量if判断

2. 直白场景区分

  • 想用统一方式创建OLED/LCD屏幕 →简单工厂

  • 第三方老旧屏幕接口和项目标准不一样 →适配器模式

  • 项目外设多、后期频繁新增,不想写switch →注册器模式

  • 滤波、CRC校验、屏幕刷新多种算法来回切换 →策略模式

六、组合使用(工业级标准架构)

在成熟的嵌入式商业项目中,四种模式不会单独使用,最优组合方案:

适配器 + 注册器 + 策略模式

  1. 适配器:统一所有第三方、自研、老旧外设的接口;

  2. 注册器:集中管理所有适配完成的外设,实现插件化;

  3. 策略模式:针对单个外设的功能,切换不同算法逻辑;

该架构解耦程度拉满,也是大厂嵌入式项目的主流开发规范。

总结

嵌入式开发者无需盲目学习全部23种设计模式,吃透以上4大核心模式,足以应对95%以上的裸机、RTOS、Linux嵌入式开发场景。

设计模式的本质从不是复杂化代码,而是解耦、复用、易拓展。根据业务场景择优使用,才能写出高质量、易维护的工业级C语言代码。

这是全网最直白的总结,帮你彻底区分四个容易混淆的模式:

1. 简单工厂模式

核心:只管【创建对象】

作用:统一创建硬件对象(OLED/LCD),上层不用手动new。弊端:内部依赖switch,新增硬件要改工厂。

2. 适配器模式

核心:只管【兼容接口】

作用:第三方驱动、老旧驱动接口不统一,写一层适配器做“翻译”,适配现有系统。

3. 注册器模式

核心:只管【统一管理】

作用:硬件自己注册、上层查表使用,干掉switch,升级版工厂模式,插件化开发。

4. 策略模式

核心:只管【切换算法】

作用:同一个功能,多种不同实现方式,动态切换算法(滤波、刷新、校验)。

六、一句话终极口诀

  • 简单工厂:我帮你造对象

  • 适配器模式:我帮你改接口

  • 注册器模式:你来报名,我管理

  • 策略模式:多种算法,随便换

总结

策略模式不做对象创建、不做接口适配、不做设备管理;它专门解决多算法切换的业务问题。

在嵌入式实际项目中,注册器 + 策略模式组合使用,就是工业级插件化架构。

http://www.cnnetsun.cn/news/2903872.html

相关文章:

  • WaveTools鸣潮工具箱:三步解锁120FPS帧率,游戏体验全面提升
  • Switch大气层整合包:3个场景解决你的破解系统烦恼
  • 【学习笔记】《Python编程 从入门到实践》第9章:类、继承、组合与面向对象编程
  • 有店铺id查详情 没有查所有
  • 耽误年报变更?营业执照遗失登报怎么弄?附2026合规登报流程
  • BetterJoy完整实战指南:在Windows上完美使用Switch手柄的终极解决方案
  • Windows控制台打印UTF-8出现乱码解决
  • 德州诈唬频率怎么算?妙懂德州:诈唬不是敢不敢,是比例对不对
  • 2026申请香港身份怎么挑靠谱中介?3 家中介真实测评对比来了
  • Linux平台纯C++实现的HTTP长轮询聊天系统,含服务端与命令行客户端
  • D2DX宽屏补丁:让经典《暗黑破坏神2》在现代PC上焕发新生的终极解决方案
  • 基于plc的楼宇供电控制系统及综合防雷设计23(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码
  • 素数查找程序
  • 链表解题总结
  • 40外语专业学生如何用 AI 训练翻译、口语和跨文化表达能力
  • M68000编程模型与指令集深度解析:从经典架构到现代编程思维
  • 微信开放平台接入AI智能体:超级App变身Agent平台
  • 抖音无水印下载终极指南:免费批量下载工具完全教程
  • Boss Show Time:招聘信息时间可视化的终极解决方案
  • 大语言模型如何革新用户去匿名化技术
  • 深度解析constexpr-8cc架构:从ELVM IR到编译时计算
  • 无人配送车全解析:从技术原理到未来市场,一篇读懂
  • 告别手动刷百鬼夜行:阴阳师脚本如何让碎片收集效率提升300%
  • 别再乱用字符串存日期了!GaussDB日期/时间类型与TO_DATE、TO_CHAR函数的最佳实践
  • 3分钟搞定扫描文档优化:ScanTailor让纸质文档秒变电子版
  • 5分钟掌握Rufus:免费USB启动盘制作工具终极指南
  • Python 爬虫实战:雪球社区投资观点数据爬取与分析
  • Python 高手编程系列三千三百八十八:微观分析
  • TTS-Vue:从命令行到语音合成的桌面应用开发实战
  • 突破性城通网盘解析工具:告别限速,实现高速下载的革命性方案