浅谈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 反而是最务实的选择。同时,"代码又不需要频繁变动,何必过度设计"有些产品,出厂就定版了,代码可能一辈子不改。对这种项目,花时间做架构设计确实性价比不高。能跑就行,稳定压倒一切。另外,"团队里没人看得懂,反而增加维护成本"这一点其实挺致命的。如果你用了观察者模式,但团队其他人完全不了解这个概念,那调试的时候他们看到回调跳来跳去,只会更头疼。设计模式的前提是团队有共识。

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

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

相关推荐
23.1 小时前
【Linux】grep -F 及 双横线--的妙用
linux·命令模式
橙露1 小时前
Linux 驱动入门:字符设备驱动框架与编写流程
linux·运维·服务器
hong1616881 小时前
TypeScript类型断言
linux·javascript·typescript
算法鑫探2 小时前
10个数下标排序:最大值、最小值与平均值(下)
c语言·数据结构·算法·排序算法·新人首发
少司府2 小时前
C++基础入门:类和对象(中)
c语言·开发语言·c++·类和对象·运算符重载·默认成员函数
南境十里·墨染春水2 小时前
Linux学习进展 进程管理命令 及文件压缩解压
linux·运维·笔记·学习
航Hang*2 小时前
第2章:进阶Linux系统——第4节:配置与管理NFS服务器
linux·运维·服务器·笔记·学习·vmware
橘子编程2 小时前
操作系统原理:从入门到精通全解析
java·linux·开发语言·windows·计算机网络·面试
亚空间仓鼠3 小时前
OpenEuler系统常用服务(三)
linux·运维·服务器·网络
爱编码的小八嘎3 小时前
C语言完美演绎7-5
c语言