浅谈PC开发中的设计模式搬迁到ARM开发

PC开发有大约二十三种设计模式,在ARM开发中能有效用到的可能也就五六种。但这五六种,一旦用对了,代码质量会有质的提升。

状态机典例

几乎所有实时性要求高的ARM系统都涉及状态管理:通信协议解析、设备工作模式切换、UI 界面流转、电机控制......只要你的系统存在"在不同条件下做不同事情"的逻辑,就应该考虑状态机。

cpp 复制代码
//一般逻辑
void motor_control(void) {
    if (mode == 1) {
        if (speed > 100 && temp < 80) {
            // 正常运行逻辑...
            if (error_flag) {
                // 错误处理...
                mode = 3;
            }
        }
    } else if (mode == 2) {
        // 又一堆嵌套...
    } else if (mode == 3) {
        // 继续嵌套...
    }
}

//状态机思想
typedef enum { IDLE, RUNNING, FAULT, STOPPING } MotorState;

// 函数指针表 ------ 每个状态对应一个处理函数
static void (*state_handler[])(void) = {
    [IDLE]     = handle_idle,
    [RUNNING]  = handle_running,
    [FAULT]    = handle_fault,
    [STOPPING] = handle_stopping,
};

void motor_control(void) {
    state_handler[current_state]();  
}

状态机最大的好处是:新增一个状态,只需要加一个处理函数,不用大改已有逻辑。 这就是开闭原则在ARM开发里最接地气的体现,很好地实现了代码的解耦。

观察者模式典例

观察者模式的典型场景是事件通知。比如一个传感器采集到数据后,可能需要同时通知 LCD 刷新显示、通知数据记录模块存储、通知通信模块上传。如果在采集函数里直接调用这三个模块,耦合就很高了。

实际上,传感器不需要知道谁在监听,只负责发通知

cpp 复制代码
#define MAX_OBSERVERS 8
typedef void (*Observer)(int sensor_value);

static Observer observers[MAX_OBSERVERS];
static int observer_count = 0;

void register_observer(Observer cb) {
    if (observer_count < MAX_OBSERVERS)
        observers[observer_count++] = cb;
}

void notify_all(int value) {
    for (int i = 0; i < observer_count; i++)
        observers[i](value);
}

本质实现就是回调函数数组,传感器模块只管调 notify_all(),完全不用知道谁注册了、干了什么。模块之间解耦了,加新功能只要注册新回调就行。

策略模式典例

即"同一件事有多种做法,需要运行时切换"的场景。比如:一个通信模块,可能需要支持多种校验算法(CRC8、CRC16、CRC32),不同的协议用不同的校验。

cpp 复制代码
/*
    一般的处理是 switch 或者 if-else。
*/

typedef uint32_t (*CrcStrategy)(const uint8_t *data, size_t len);

typedef struct {
    CrcStrategy calc_crc;  // 当前使用的校验策略
    // ... 其他配置
} CommConfig;

// 切换策略就是换个函数指针
void comm_set_crc(CommConfig *cfg, CrcStrategy strategy) {
    cfg->calc_crc = strategy;
}

当然,ARM平台资源有限,搞这些抽象太浪费了。这话有一定道理。在 8 位单片机上,RAM 可能只有几百字节,Flash 也就几 KB,确实没资本搞复杂的抽象层。函数指针表虽然优雅,但每个指针也要占内存。在这类极端受限的平台上,直接写 if-else 反而是最务实的选择。同时,"代码又不需要频繁变动,何必过度设计"有些产品,出厂就定版了,代码可能一辈子不改。对这种项目,花时间做架构设计确实性价比不高。能跑就行,稳定压倒一切。另外,"团队里没人看得懂,反而增加维护成本"这一点其实挺致命的。如果你用了观察者模式,但团队其他人完全不了解这个概念,那调试的时候他们看到回调跳来跳去,只会更头疼。设计模式的前提是团队有共识。

在实际的开发中,从问题出发,而不是从模式出发。 不要想着"我要用观察者模式",而是想"传感器数据要通知好几个模块,怎么解耦"。当带着实际问题去找方案的时候,设计模式才真正有意义。

像优先级比较高的状态机,可以用在协议解析、模式切换、流程控制等;观察者模式,可以用在事件通知、传感器数据分发等;策略模式,可以用在算法切换、多平台适配等;单例模式,可以用在全局硬件资源管理等。

相关推荐
闻哥2 小时前
23种设计模式深度解析:从原理到实战落地
java·jvm·spring boot·设计模式·面试
Kurbaneli2 小时前
C语言过时了吗?2025年仍不可替代
c语言·开发语言
智者知已应修善业4 小时前
【PAT乙级真题解惑1012数字分类】2025-3-29
c语言·c++·经验分享·笔记·算法
Hello.Reader4 小时前
从 0 到 1 理解硬盘数据恢复工具原理与工程实现
linux·运维·服务器·网络·数据库
资深web全栈开发4 小时前
设计模式之享元模式 (Flyweight Pattern)
设计模式·享元模式
v_for_van4 小时前
力扣刷题记录6(无算法背景,纯C语言)
c语言·算法·leetcode
爱编码的小八嘎4 小时前
第2章 认识CPU-2.3 32位微处理器(1)
c语言
BackCatK Chen5 小时前
第十五章 吃透C语言结构与数据形式:struct/union/typedef全解析
c语言·开发语言·数据结构·typedef·结构体·函数指针·联合体
『往事』&白驹过隙;5 小时前
C/C++中的格式化输出与输入snprintf&sscanf
linux·c语言·c++·笔记·学习·iot·系统调用