设计模式在嵌入式系统中的应用完全指南
设计模式是软件工程中经过验证的解决方案,是前辈们智慧的结晶。在嵌入式开发中,合理运用设计模式可以提高代码的可维护性、可扩展性和可测试性。本文将带你深入理解设计模式,并掌握在嵌入式领域应用它们的正确姿势。
一、设计模式概述
1.1 什么是设计模式
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的代码设计经验总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
1.2 设计模式分类
二、创建型模式
创建型模式主要关注对象的创建过程,帮助我们更优雅地创建对象。
2.1 单例模式 (Singleton)
核心思想
确保一个类只有一个实例,并提供一个全局访问点。
嵌入式应用场景
- 硬件抽象层 (HAL) 管理
- 系统配置管理器
- 串口/USB 等外设的唯一访问点
代码示例
// 单例模式 - 线程安全 (适用于 RTOS)#include <stdint.h>#include <stdbool.h>
typedef struct { uint32_t baudrate; uint8_t parity; uint8_t stop_bits; // 其他串口配置...} UART_Config;
typedef struct { UART_Config config; bool initialized; // 私有数据} UART_Manager;
static UART_Manager* instance = NULL;static uint8_t mutex_locked = 0;
// 双检查锁定 (Double-Checked Locking)UART_Manager* UART_Manager_GetInstance(void) { if (instance == NULL) { // 第一次检查 if (mutex_locked == 0) { mutex_locked = 1; // 临界区 if (instance == NULL) { // 第二次检查 static UART_Manager uart = {0}; instance = &uart; } mutex_locked = 0; } } return instance;}
// 简单版本 (裸机环境)#define UART_MANAGER_GET() \ do { \ static UART_Manager *inst = NULL; \ if (inst == NULL) { \ static UART_Manager uart = {.initialized = false}; \ inst = &uart; \ } \ return inst; \ } while(0)// 实际应用:系统配置管理器typedef struct { System_Config data; bool dirty;} Config_Manager;
static Config_Manager *Config_Get(void) { static Config_Manager mgr = { .data = { .clock_freq = 72000000, .tick_rate = 1000, .power_mode = POWER_NORMAL, }, .dirty = false, }; return &mgr;}
void Config_SetClock(uint32_t freq) { Config_Manager *cfg = Config_Get(); cfg->data.clock_freq = freq; cfg->dirty = true;}2.2 工厂方法模式 (Factory Method)
核心思想
定义一个创建对象的接口,但让子类决定实例化哪个类。
嵌入式应用场景
- 传感器驱动的统一管理
- 通信协议的不同实现
- 设备驱动的动态加载
代码示例
// 传感器驱动工厂#include <stdint.h>#include <stdbool.h>
// 传感器抽象接口typedef struct Sensor Sensor;
struct Sensor { const char *name; int (*init)(void); int (*read)(float *value); int (*deinit)(void);};
// 抽象工厂接口typedef struct { Sensor* (*create)(uint8_t id); void (*destroy)(Sensor *sensor);} Sensor_Factory;
// 温度传感器typedef struct { Sensor base; float calibration;} Temp_Sensor;
static int temp_init(void) { // 初始化温度传感器 return 0;}
static int temp_read(float *value) { *value = 25.0f + (float)(rand() % 100) / 100.0f; return 0;}
static Sensor temp_sensor = { .name = "Temperature", .init = temp_init, .read = temp_read,};
// 湿度传感器typedef struct { Sensor base; uint8_t mode;} Humidity_Sensor;
static int humidity_read(float *value) { *value = 60.0f + (float)(rand() % 300) / 10.0f; return 0;}
// 工厂实现static Sensor* sensor_factory_create(uint8_t type) { switch(type) { case 0: // 温度传感器 return &temp_sensor; case 1: // 湿度传感器 // 返回湿度传感器实例 break; default: return NULL; } return NULL;}
static Sensor_Factory factory = { .create = sensor_factory_create, .destroy = NULL,};
// 使用示例void sensor_demo(void) { Sensor *temp = factory.create(0); if (temp) { temp->init(); float value; temp->read(&value); printf("Temperature: %.2f\n", value); }}2.3 抽象工厂模式 (Abstract Factory)
核心思想
提供一个创建一系列相关对象的接口,而无需指定它们具体的类。
嵌入式应用场景
- 不同平台 (STM32/ESP32) 的统一抽象
- 不同产品线的硬件抽象
// 抽象工厂 - 跨平台硬件抽象typedef struct { void (*gpio_init)(uint8_t pin, uint8_t mode); void (*gpio_write)(uint8_t pin, uint8_t value); int (*gpio_read)(uint8_t pin); void (*delay_ms)(uint32_t ms); int (*uart_send)(uint8_t ch); int (*uart_recv)(uint8_t *ch);} HAL_Interface;
static HAL_Interface *hal = NULL;
void HAL_SetImplementation(HAL_Interface *impl) { hal = impl;}
// STM32 实现static HAL_Interface stm32_hal = { .gpio_init = stm32_gpio_init, .gpio_write = stm32_gpio_write, .gpio_read = stm32_gpio_read, .delay_ms = HAL_Delay, .uart_send = UART_Send, .uart_recv = UART_Recv,};
// ESP32 实现static HAL_Interface esp32_hal = { .gpio_init = esp32_gpio_init, .gpio_write = esp32_gpio_write, .gpio_read = esp32_gpio_read, .delay_ms = vTaskDelay, .uart_send = uart_write_bytes, .uart_recv = uart_read_bytes,};
// 平台选择void Platform_Init(bool is_stm32) { HAL_SetImplementation(is_stm32 ? &stm32_hal : &esp32_hal);}2.4 建造者模式 (Builder)
核心思想
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
嵌入式应用场景
- 复杂配置的构建
- 通信协议的组装
- 数据帧的构造
// 建造者模式 - CAN 报文构建typedef struct { uint32_t id; uint8_t dlc; uint8_t data[8]; bool ext_id; bool rtr;} CAN_Message;
typedef struct { CAN_Message *msg;} CAN_MessageBuilder;
CAN_MessageBuilder CAN_Builder_Init(void) { static CAN_Message msg = {0}; CAN_MessageBuilder builder = { .msg = &msg }; return builder;}
CAN_MessageBuilder CAN_Builder_Id(CAN_MessageBuilder self, uint32_t id) { self.msg->id = id; return self;}
CAN_MessageBuilder CAN_Builder_Data(CAN_MessageBuilder self, uint8_t *data, uint8_t len) { for (uint8_t i = 0; i < len && i < 8; i++) { self.msg->data[i] = data[i]; } self.msg->dlc = len; return self;}
CAN_MessageBuilder CAN_Builder_ExtId(CAN_MessageBuilder self) { self.msg->ext_id = true; return self;}
CAN_Message CAN_Builder_Build(CAN_MessageBuilder self) { return *self.msg;}
// 使用示例void can_send_example(void) { CAN_Message msg = CAN_Builder_Init() .Id(0x123) .ExtId() .Data((uint8_t[]){0x01, 0x02, 0x03}, 3) .Build();
CAN_Send(&msg);}2.5 原型模式 (Prototype)
核心思想
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
嵌入式应用场景
- 配置模板的复制
- 协议数据包的批量生成
// 原型模式 - 配置模板typedef struct { char name[32]; uint32_t period; uint8_t priority; void (*callback)(void*);} Task_Config;
typedef struct Task_Config { struct Task_Config *next; Task_Config proto;} Task_Prototype;
static Task_Config sensor_task_proto = { .name = "Sensor", .period = 100, .priority = 5, .callback = NULL,};
static Task_Config comm_task_proto = { .name = "Comm", .period = 50, .priority = 3, .callback = NULL,};
Task_Config* Task_Clone(Task_Config *proto) { Task_Config *new_task = malloc(sizeof(Task_Config)); if (new_task) { memcpy(new_task, proto, sizeof(Task_Config)); } return new_task;}
// 使用Task_Config *task1 = Task_Clone(&sensor_task_proto);strcpy(task1->name, "TempSensor");task1->period = 200;三、结构型模式
结构型模式关注如何组合类和对象以获得更大的结构。
3.1 适配器模式 (Adapter)
核心思想
将一个类的接口转换成客户希望的另外一个接口。
嵌入式应用场景
- 不同传感器的统一接口
- 旧驱动在新系统上的适配
- 第三方库的整合
// 适配器模式 - 统一传感器接口#include <stdint.h>
// 目标接口 (嵌入式通用传感器接口)typedef struct { int (*read_raw)(void *buffer, uint16_t size); int (*read_float)(float *value); int (*init)(void); int (*deinit)(void);} Sensor_Interface;
// 旧版温度传感器驱动 (遗留代码)typedef struct { uint16_t raw_value; float temperature;} Legacy_TempSensor;
int legacy_temp_read(uint16_t *raw) { // 旧驱动实现 *raw = 2500; return 0;}
float legacy_temp_convert(uint16_t raw) { return (float)raw / 100.0f - 273.15f;}
// 适配器 - 将旧驱动适配到新接口static int adapter_read_raw(void *buffer, uint16_t size) { if (size < sizeof(uint16_t)) return -1; Legacy_TempSensor *sensor = (Legacy_TempSensor*)buffer; return legacy_temp_read(&sensor->raw_value);}
static int adapter_read_float(float *value) { uint16_t raw; legacy_temp_read(&raw); *value = legacy_temp_convert(raw); return 0;}
static int adapter_init(void) { // 初始化旧驱动 return 0;}
static int adapter_deinit(void) { return 0;}
static Sensor_Interface temp_sensor_adapter = { .read_raw = adapter_read_raw, .read_float = adapter_read_float, .init = adapter_init, .deinit = adapter_deinit,};3.2 桥接模式 (Bridge)
核心思想
将抽象部分与实现部分分离,使它们可以独立变化。
嵌入式应用场景
- 平台无关的驱动架构
- 通信协议与传输层分离
// 桥接模式 - 通信协议抽象#include <stdint.h>
// 实现接口 (传输层)typedef struct Transport_ops { int (*open)(void *ctx); int (*send)(void *ctx, const uint8_t *data, uint16_t len); int (*recv)(void *ctx, uint8_t *data, uint16_t len); int (*close)(void *ctx);} Transport_ops;
// 抽象协议层typedef struct { Transport_ops *transport; void *transport_ctx;} Protocol;
// UART 传输实现typedef struct { uint8_t uart_id;} UART_Context;
static int uart_open(void *ctx) { return 0; }static int uart_send(void *ctx, const uint8_t *data, uint16_t len) { UART_Context *c = (UART_Context*)ctx; // 发送数据... return len;}static int uart_recv(void *ctx, uint8_t *data, uint16_t len) { return 0;}static int uart_close(void *ctx) { return 0; }
static Transport_ops uart_transport = { .open = uart_open, .send = uart_send, .recv = uart_recv, .close = uart_close,};
// SPI 传输实现static Transport_ops spi_transport = { .open = spi_open, .send = spi_send, .recv = spi_recv, .close = spi_close,};
// 协议使用void Protocol_Init(Protocol *proto, Transport_ops *trans) { proto->transport = trans;}
void Protocol_Send(Protocol *proto, uint8_t *data, uint16_t len) { proto->transport->send(proto->transport_ctx, data, len);}3.3 组合模式 (Composite)
核心思想
将对象组合成树形结构以表示”部分-整体”的层次结构。
嵌入式应用场景
- 设备树的表示
- 菜单系统
- 文件系统
// 组合模式 - 设备管理#include <stdint.h>#include <stdbool.h>
typedef struct Device Device;
typedef struct { int (*init)(Device *dev); int (*start)(Device *dev); int (*stop)(Device *dev); int (*ioctl)(Device *dev, uint32_t cmd, void *arg);} Device_Ops;
struct Device { const char *name; Device_Ops *ops; Device *parent; Device *children; Device *next; bool enabled;};
int Device_Init(Device *dev) { if (dev && dev->ops && dev->ops->init) { return dev->ops->init(dev); } return -1;}
int Device_Start(Device *dev) { int ret = 0; if (dev && dev->ops && dev->ops->start) { ret = dev->ops->start(dev); } // 启动所有子设备 for (Device *child = dev->children; child != NULL; child = child->next) { ret |= Device_Start(child); } dev->enabled = true; return ret;}
int Device_Stop(Device *dev) { int ret = 0; // 停止所有子设备 for (Device *child = dev->children; child != NULL; child = child->next) { ret |= Device_Stop(child); } if (dev && dev->ops && dev->ops->stop) { ret |= dev->ops->stop(dev); } dev->enabled = false; return ret;}
// 添加子设备void Device_AddChild(Device *parent, Device *child) { child->parent = parent; child->next = parent->children; parent->children = child;}3.4 装饰器模式 (Decorator)
核心思想
动态地给一个对象添加一些额外的职责。
嵌入式应用场景
- 传感器数据的预处理
- 通信数据的加密/压缩
- 日志记录增强
// 装饰器模式 - 数据处理流水线#include <stdint.h>#include <string.h>
typedef struct DataProcessor DataProcessor;
typedef int (*ProcessFunc)(DataProcessor *proc, uint8_t *data, uint16_t len);
struct DataProcessor { ProcessFunc process; DataProcessor *next; // 链式装饰 void *context;};
// 基础处理器int base_process(DataProcessor *proc, uint8_t *data, uint16_t len) { return len;}
// 装饰器 - 校验和typedef struct { DataProcessor base;} Checksum_Decorator;
int checksum_process(DataProcessor *proc, uint8_t *data, uint16_t len) { uint8_t sum = 0; for (uint16_t i = 0; i < len; i++) { sum += data[i]; } data[len] = sum; // 调用下一个处理器 if (proc->next) { return proc->next->process(proc->next, data, len + 1); } return len + 1;}
// 装饰器 - 加密typedef struct { DataProcessor base; uint8_t key[16];} Encrypt_Decorator;
int encrypt_process(DataProcessor *proc, uint8_t *data, uint16_t len) { Encrypt_Decorator *enc = (Encrypt_Decorator*)proc; // XOR 加密 for (uint16_t i = 0; i < len; i++) { data[i] ^= enc->key[i % 16]; } if (proc->next) { return proc->next->process(proc->next, data, len); } return len;}
// 使用示例void data_pipeline_demo(void) { // 创建处理器链 static Checksum_Decorator cs = {0}; cs.base.process = checksum_process;
static Encrypt_Decorator enc = {0}; enc.base.process = encrypt_process; memset(enc.key, 0x5A, 16);
// 链式连接: 加密 -> 校验和 -> 基础 enc.base.next = &cs.base; cs.base.next = NULL;
uint8_t data[] = "Hello Embedded"; int len = sizeof(data) - 1;
// 处理数据 len = enc.base.process(&enc.base, data, len);}3.5 外观模式 (Facade)
核心思想
为复杂的子系统提供一个统一的接口。
嵌入式应用场景
- 硬件抽象层 (HAL)
- 统一 API 接口
- 初始化系统
// 外观模式 - 统一的硬件初始化接口#include <stdint.h>
typedef struct { int (*gpio_init)(void); int (*uart_init)(void); int (*spi_init)(void); int (*i2c_init)(void); int (*adc_init)(void); int (*timer_init)(void);} HAL_Facade;
static int GPIO_Init(void) { /* 实现 */ return 0; }static int UART_Init(void) { /* 实现 */ return 0; }static int SPI_Init(void) { /* 实现 */ return 0; }static int I2C_Init(void) { /* 实现 */ return 0; }static int ADC_Init(void) { /* 实现 */ return 0; }static int Timer_Init(void) { /* 实现 */ return 0; }
static HAL_Facade hal = { .gpio_init = GPIO_Init, .uart_init = UART_Init, .spi_init = SPI_Init, .i2c_init = I2C_Init, .adc_init = ADC_Init, .timer_init = Timer_Init,};
// 统一初始化int System_InitAll(void) { int ret = 0; ret |= hal.gpio_init(); ret |= hal.uart_init(); ret |= hal.spi_init(); ret |= hal.i2c_init(); ret |= hal.adc_init(); ret |= hal.timer_init(); return ret;}3.6 享元模式 (Flyweight)
核心思想
运用共享技术有效地支持大量细粒度对象。
嵌入式应用场景
- 状态机的高效实现
- 大量相似对象
- 固件资源受限环境
// 享元模式 - 事件处理#include <stdint.h>#include <stdbool.h>
typedef struct EventType EventType;typedef struct Event Event;
// 享元 - 事件类型 (共享)struct EventType { uint8_t id; const char *name; void (*handler)(Event *event); EventType *next;};
// 具体享元对象struct Event { EventType *type; uint32_t timestamp; void *data; uint16_t data_len;};
// 享元工厂static EventType event_types[16];static uint8_t event_type_count = 0;
EventType* EventType_Register(uint8_t id, const char *name, void (*handler)(Event*)) { // 查找是否已存在 for (uint8_t i = 0; i < event_type_count; i++) { if (event_types[i].id == id) { return &event_types[i]; } } // 创建新的享元 if (event_type_count < 16) { EventType *et = &event_types[event_type_count++]; et->id = id; et->name = name; et->handler = handler; return et; } return NULL;}
// 使用享元创建事件Event* Event_Create(uint8_t type_id, void *data, uint16_t len) { static Event pool[32]; // 事件对象池 static uint8_t pool_idx = 0;
Event *event = &pool[pool_idx++ % 32]; event->type = EventType_Register(type_id, NULL, NULL); event->data = data; event->data_len = len; event->timestamp = HAL_GetTick(); return event;}3.7 代理模式 (Proxy)
核心思想
为其他对象提供一种代理以控制对这个对象的访问。
嵌入式应用场景
- 硬件访问控制
- 资源懒加载
- 访问权限控制
// 代理模式 - 硬件资源访问控制#include <stdint.h>#include <stdbool.h>
typedef struct HW_Device HW_Device;typedef struct HW_Proxy HW_Proxy;
typedef int (*ReadFunc)(HW_Device *dev, uint8_t *buf, uint16_t len);typedef int (*WriteFunc)(HW_Device *dev, const uint8_t *buf, uint16_t len);
struct HW_Device { ReadFunc read; WriteFunc write; void *base_addr; bool initialized;};
struct HW_Proxy { HW_Device *real_device; bool access_granted; uint32_t access_count;};
// 权限检查代理int proxy_read(HW_Device *dev, uint8_t *buf, uint16_t len) { HW_Proxy *proxy = (HW_Proxy*)dev; if (!proxy->access_granted) { return -1; // 无权限 } proxy->access_count++; return proxy->real_device->read(proxy->real_device, buf, len);}
int proxy_write(HW_Device *dev, const uint8_t *buf, uint16_t len) { HW_Proxy *proxy = (HW_Proxy*)dev; if (!proxy->access_granted) { return -1; } return proxy->real_device->write(proxy->real_device, buf, len);}
void HW_Proxy_Init(HW_Proxy *proxy, HW_Device *real) { proxy->real_device = real; proxy->access_granted = false; proxy->access_count = 0;}四、行为型模式
行为型模式关注对象之间的通信和职责分配。
4.1 观察者模式 (Observer)
核心思想
定义对象间的一对多依赖关系,当一个对象改变状态时,所有依赖它的对象都会得到通知。
嵌入式应用场景
- 事件驱动系统
- 传感器数据更新通知
- UI 更新机制
// 观察者模式 - 传感器数据发布/订阅#include <stdint.h>#include <stdbool.h>#include <stdlib.h>
#define MAX_OBSERVERS 8
typedef struct Observer Observer;typedef struct Subject Subject;
struct Observer { void (*update)(void *data); const char *name;};
struct Subject { Observer *observers[MAX_OBSERVERS]; uint8_t observer_count; void *data;};
void Subject_Init(Subject *subject) { subject->observer_count = 0; subject->data = NULL;}
bool Subject_Attach(Subject *subject, Observer *observer) { if (subject->observer_count >= MAX_OBSERVERS) { return false; } subject->observers[subject->observer_count++] = observer; return true;}
bool Subject_Detach(Subject *subject, Observer *observer) { for (uint8_t i = 0; i < subject->observer_count; i++) { if (subject->observers[i] == observer) { for (uint8_t j = i; j < subject->observer_count - 1; j++) { subject->observers[j] = subject->observers[j + 1]; } subject->observer_count--; return true; } } return false;}
void Subject_Notify(Subject *subject) { for (uint8_t i = 0; i < subject->observer_count; i++) { subject->observers[i]->update(subject->data); }}
// 使用示例 - 温度传感器监控static Subject temp_subject;
void display_update(void *data) { float temp = *(float*)data; printf("Display: %.1f°C\n", temp);}
void alarm_update(void *data) { float temp = *(float*)data; if (temp > 30.0f) { printf("ALARM: High temperature!\n"); }}
void log_update(void *data) { printf("Log: Temperature updated\n");}
void sensor_demo(void) { Subject_Init(&temp_subject);
static Observer observers[3] = { {.update = display_update, .name = "Display"}, {.update = alarm_update, .name = "Alarm"}, {.update = log_update, .name = "Log"}, };
Subject_Attach(&temp_subject, &observers[0]); Subject_Attach(&temp_subject, &observers[1]); Subject_Attach(&temp_subject, &observers[2]);
// 温度变化,通知所有观察者 float temp = 25.5f; temp_subject.data = &temp; Subject_Notify(&temp_subject);}4.2 状态模式 (State)
核心思想
允许对象在内部状态改变时改变它的行为。
嵌入式应用场景
- 状态机实现
- 协议状态管理
- 设备运行状态控制
// 状态模式 - 状态机#include <stdint.h>#include <stdbool.h>
typedef struct State State;typedef struct StateMachine StateMachine;
struct State { const char *name; int (*enter)(StateMachine *sm); int (*exit)(StateMachine *sm); int (*handle)(StateMachine *sm, uint32_t event);};
struct StateMachine { State *current_state; State *states; uint8_t state_count; void *context;};
int StateMachine_Transition(StateMachine *sm, uint8_t new_state) { if (new_state >= sm->state_count) { return -1; } if (sm->current_state && sm->current_state->exit) { sm->current_state->exit(sm); } sm->current_state = &sm->states[new_state]; if (sm->current_state->enter) { sm->current_state->enter(sm); } return 0;}
int StateMachine_Handle(StateMachine *sm, uint32_t event) { if (sm->current_state && sm->current_state->handle) { return sm->current_state->handle(sm, event); } return -1;}
// LED 状态机示例typedef enum { LED_OFF, LED_ON, LED_BLINK, LED_STATE_COUNT} LED_State;
static int led_on_enter(StateMachine *sm) { HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET); return 0;}
static int led_off_enter(StateMachine *sm) { HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET); return 0;}
static int led_handle(StateMachine *sm, uint32_t event) { switch (event) { case 0: // 开启 StateMachine_Transition(sm, LED_ON); break; case 1: // 关闭 StateMachine_Transition(sm, LED_OFF); break; case 2: // 切换 if (sm->current_state->enter == led_on_enter) { StateMachine_Transition(sm, LED_OFF); } else { StateMachine_Transition(sm, LED_ON); } break; } return 0;}
static State led_states[LED_STATE_COUNT] = { [LED_OFF] = {.name = "OFF", .enter = led_off_enter, .handle = led_handle}, [LED_ON] = {.name = "ON", .enter = led_on_enter, .handle = led_handle},};4.3 策略模式 (Strategy)
核心思想
定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。
嵌入式应用场景
- 不同算法切换
- 通信协议选择
- 数据压缩方式选择
// 策略模式 - 通信协议选择#include <stdint.h>
typedef struct ProtocolStrategy ProtocolStrategy;
typedef int (*EncodeFunc)(const uint8_t *in, uint16_t in_len, uint8_t *out, uint16_t *out_len);typedef int (*DecodeFunc)(const uint8_t *in, uint16_t in_len, uint8_t *out, uint16_t *out_len);
struct ProtocolStrategy { const char *name; EncodeFunc encode; DecodeFunc decode;};
// JSON 策略static int json_encode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint16_t *out_len) { // JSON 编码实现 return 0;}
// 二进制协议策略static int binary_encode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint16_t *out_len) { // 二进制编码实现 return 0;}
// Protobuf 风格策略static int protobuf_encode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint16_t *out_len) { // Protobuf 编码实现 return 0;}
static ProtocolStrategy strategies[] = { {.name = "JSON", .encode = json_encode}, {.name = "Binary", .encode = binary_encode}, {.name = "Protobuf", .encode = protobuf_encode},};
// 使用typedef struct { ProtocolStrategy *strategy; uint8_t strategy_id;} Comm_Context;
void Comm_SetProtocol(Comm_Context *ctx, uint8_t id) { if (id < 3) { ctx->strategy = &strategies[id]; ctx->strategy_id = id; }}
int Comm_Send(Comm_Context *ctx, const uint8_t *data, uint16_t len) { uint8_t buffer[256]; uint16_t out_len; return ctx->strategy->encode(data, len, buffer, &out_len);}4.4 命令模式 (Command)
核心思想
将请求封装成对象,从而允许你参数化不同请求。
嵌入式应用场景
- 命令队列
- 撤销/重做功能
- 任务调度
// 命令模式 - 命令队列与执行#include <stdint.h>#include <stdbool.h>
typedef struct Command Command;
typedef int (*ExecuteFunc)(Command *cmd);typedef int (*UndoFunc)(Command *cmd);
struct Command { ExecuteFunc execute; UndoFunc undo; void *data; const char *name;};
typedef struct { Command *queue[32]; uint8_t head; uint8_t tail; uint8_t count;} CommandQueue;
int CommandQueue_Init(CommandQueue *q) { q->head = 0; q->tail = 0; q->count = 0; return 0;}
bool CommandQueue_IsEmpty(CommandQueue *q) { return q->count == 0;}
bool CommandQueue_IsFull(CommandQueue *q) { return q->count >= 32;}
int CommandQueue_Push(CommandQueue *q, Command *cmd) { if (CommandQueue_IsFull(q)) { return -1; } q->queue[q->tail] = cmd; q->tail = (q->tail + 1) % 32; q->count++; return 0;}
Command* CommandQueue_Pop(CommandQueue *q) { if (CommandQueue_IsEmpty(q)) { return NULL; } Command *cmd = q->queue[q->head]; q->head = (q->head + 1) % 32; q->count--; return cmd;}
// 具体命令 - LED 控制typedef struct { Command base; uint8_t pin; uint8_t action; // 0: off, 1: on, 2: toggle} LED_Command;
static int led_execute(Command *cmd) { LED_Command *led = (LED_Command*)cmd; switch (led->action) { case 0: HAL_GPIO_WritePin(GPIOA, led->pin, 0); break; case 1: HAL_GPIO_WritePin(GPIOA, led->pin, 1); break; case 2: HAL_GPIO_TogglePin(GPIOA, led->pin); break; } return 0;}
static int led_undo(Command *cmd) { LED_Command *led = (LED_Command*)cmd; led->action = (led->action == 1) ? 0 : 1; return led_execute(cmd);}
LED_Command led_on_cmd = { .base = {.execute = led_execute, .undo = led_undo}, .pin = LED_PIN, .action = 1,};
// 使用示例void command_demo(void) { CommandQueue queue; CommandQueue_Init(&queue);
CommandQueue_Push(&queue, (Command*)&led_on_cmd); // ... 添加更多命令
while (!CommandQueue_IsEmpty(&queue)) { Command *cmd = CommandQueue_Pop(&queue); cmd->execute(cmd); }}4.5 模板方法模式 (Template Method)
核心思想
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
嵌入式应用场景
- 驱动框架
- 初始化流程
- 协议处理
// 模板方法 - 驱动初始化框架#include <stdint.h>
typedef struct Driver Driver;
typedef int (*InitFunc)(Driver *drv);typedef int (*ReadFunc)(Driver *drv, void *buf, uint16_t len);typedef int (*WriteFunc)(Driver *drv, const void *buf, uint16_t len);typedef int (*DeinitFunc)(Driver *drv);
struct Driver { InitFunc init; ReadFunc read; WriteFunc write; DeinitFunc deinit; void *context; bool initialized;};
// 模板方法 - 标准驱动生命周期int Driver_StandardLifecycle(Driver *drv) { int ret;
// 步骤1: 检查参数 if (!drv || !drv->init || !drv->read || !drv->write) { return -1; }
// 步骤2: 初始化 (子类实现) ret = drv->init(drv); if (ret != 0) { return ret; } drv->initialized = true;
// 步骤3: 等待就绪 // (可由子类重写的钩子)
return 0;}
// 模板方法 - 读写操作int Driver_Read(Driver *drv, void *buf, uint16_t len) { if (!drv || !drv->initialized) { return -1; } return drv->read(drv, buf, len);}
int Driver_Write(Driver *drv, const void *buf, uint16_t len) { if (!drv || !drv->initialized) { return -1; } return drv->write(drv, buf, len);}
// 具体驱动 - UART 实现static int uart_driver_init(Driver *drv) { // UART 特定初始化 return 0;}
static int uart_driver_read(Driver *drv, void *buf, uint16_t len) { // UART 读取实现 return 0;}
static Driver uart_driver = { .init = uart_driver_init, .read = uart_driver_read, .write = NULL, .deinit = NULL,};4.6 责任链模式 (Chain of Responsibility)
核心思想
将请求的发送者和接收者解耦,让多个对象都有机会处理请求。
嵌入式应用场景
- 事件处理
- 权限检查
- 消息过滤
// 责任链模式 - 消息处理#include <stdint.h>#include <stdbool.h>
typedef struct Handler Handler;typedef struct Message Message;
typedef int (*HandlerFunc)(Handler *handler, Message *msg);
struct Message { uint32_t type; uint32_t priority; void *payload; uint16_t payload_len; bool handled;};
struct Handler { HandlerFunc handle; Handler *next; const char *name;};
int Handler_Handle(Handler *handler, Message *msg) { if (!handler) { return -1; }
int result = handler->handle(handler, msg);
// 如果当前处理器无法处理,传递给下一个 if (result != 0 && handler->next) { return Handler_Handle(handler->next, msg); }
return result;}
// 具体处理器 - 消息验证static int validator_handle(Handler *h, Message *msg) { if (msg->payload_len == 0 || msg->payload == NULL) { printf("[Validator] Invalid message\n"); return -1; } printf("[Validator] Message validated\n"); return 0; // 验证通过,继续传递}
// 具体处理器 - 权限检查static int auth_handle(Handler *h, Message *msg) { // 简化: 检查 priority if (msg->priority > 10) { printf("[Auth] Permission denied\n"); return -1; } printf("[Auth] Authorized\n"); return 0;}
// 具体处理器 - 消息处理static int processor_handle(Handler *h, Message *msg) { printf("[Processor] Processing message type: %lu\n", msg->type); msg->handled = true; return 0;}
// 链式组装static Handler validator = {.handle = validator_handle, .name = "Validator"};static Handler auth = {.handle = auth_handle, .name = "Auth"};static Handler processor = {.handle = processor_handle, .name = "Processor"};
void HandlerChain_Init(void) { validator.next = &auth; auth.next = &processor; processor.next = NULL;}
// 使用void message_demo(void) { HandlerChain_Init();
Message msg = { .type = 1, .priority = 5, .payload = "Hello", .payload_len = 5, .handled = false, };
Handler_Handle(&validator, &msg);}4.7 迭代器模式 (Iterator)
核心思想
提供一种方法顺序访问集合对象中的各个元素,而不需暴露该对象的内部表示。
嵌入式应用场景
- 遍历传感器列表
- 遍历设备树
- 遍历数据缓冲
// 迭代器模式 - 设备遍历#include <stdint.h>
typedef struct Device Device;typedef struct Iterator Iterator;
typedef Device* (*NextFunc)(Iterator *it);typedef bool (*HasNextFunc)(Iterator *it);typedef void (*ResetFunc)(Iterator *it);
struct Iterator { NextFunc next; HasNextFunc hasNext; ResetFunc reset; void *context; uint8_t index;};
struct Device { const char *name; uint8_t type; Device *next;};
static Device *devices = NULL;
void Device_Add(Device *dev) { dev->next = devices; devices = dev;}
// 迭代器实现static Device* device_next(Iterator *it) { Device **list = (Device**)it->context; Device *dev = list[it->index++]; return dev;}
static bool device_has_next(Iterator *it) { Device **list = (Device**)it->context; return list[it->index] != NULL;}
static void device_reset(Iterator *it) { it->index = 0;}
void DeviceIterator_Init(Iterator *it) { static Device *device_list[16];
// 收集设备到数组 uint8_t count = 0; for (Device *d = devices; d && count < 16; d = d->next) { device_list[count++] = d; } device_list[count] = NULL;
it->context = device_list; it->next = device_next; it->hasNext = device_has_next; it->reset = device_reset; it->index = 0;}
// 使用void iterator_demo(void) { static Device dev1 = {.name = "UART1", .type = 1}; static Device dev2 = {.name = "SPI1", .type = 2}; static Device dev3 = {.name = "I2C1", .type = 3};
Device_Add(&dev1); Device_Add(&dev2); Device_Add(&dev3);
Iterator it; DeviceIterator_Init(&it);
while (it.hasNext(&it)) { Device *d = it.next(&it); printf("Device: %s\n", d->name); }}4.8 中介者模式 (Mediator)
核心思想
用一个中介对象来封装一系列的对象交互。
嵌入式应用场景
- GUI 事件处理
- 多模块协调
- 总线通信
// 中介者模式 - 多模块协调#include <stdint.h>
typedef struct Mediator Mediator;typedef struct Component Component;
typedef void (*NotifyFunc)(Component *comp, Mediator *med, uint32_t event);
struct Component { NotifyFunc on_notify; const char *name; Mediator *mediator;};
struct Mediator { Component **components; uint8_t component_count;};
void Mediator_Register(Mediator *med, Component *comp) { if (med->component_count < 16) { comp->mediator = med; med->components[med->component_count++] = comp; }}
void Mediator_Notify(Mediator *med, Component *sender, uint32_t event) { // 广播给其他组件 for (uint8_t i = 0; i < med->component_count; i++) { Component *comp = med->components[i]; if (comp != sender && comp->on_notify) { comp->on_notify(comp, med, event); } }}
// 具体组件static Mediator system_mediator;
static void sensor_on_notify(Component *comp, Mediator *med, uint32_t event) { printf("[%s] Received event: %lu\n", comp->name, event);}
static void display_on_notify(Component *comp, Mediator *med, uint32_t event) { printf("[%s] Received event: %lu\n", comp->name, event);}
static Component sensor = {.name = "Sensor", .on_notify = sensor_on_notify};static Component display = {.name = "Display", .on_notify = display_on_notify};static Component button = {.name = "Button", .on_notify = NULL};
void mediator_demo(void) { Mediator_Register(&system_mediator, &sensor); Mediator_Register(&system_mediator, &display); Mediator_Register(&system_mediator, &button);
// 按钮按下,通知传感器和显示器 Mediator_Notify(&system_mediator, &button, 0x01);}4.9 备忘录模式 (Memento)
核心思想
在不破坏封装性的前提下捕获对象的内部状态。
嵌入式应用场景
- 配置保存与恢复
- 系统状态快照
- 错误恢复
// 备忘录模式 - 配置保存/恢复#include <stdint.h>#include <string.h>
typedef struct { uint32_t clock; uint8_t power_mode; uint8_t baudrate; bool debug_enabled;} SystemConfig;
typedef struct { SystemConfig state; uint32_t timestamp;} ConfigMemento;
typedef struct { SystemConfig current; ConfigMemento backup; bool has_backup;} ConfigManager;
void Config_Save(ConfigManager *mgr) { mgr->backup.state = mgr->current; mgr->backup.timestamp = HAL_GetTick(); mgr->has_backup = true;}
void Config_Restore(ConfigManager *mgr) { if (mgr->has_backup) { mgr->current = mgr->backup.state; }}
void Config_Update(ConfigManager *mgr, uint32_t clock, uint8_t mode) { mgr->current.clock = clock; mgr->current.power_mode = mode;}4.10 访问者模式 (Visitor)
核心思想
表示一个作用于某对象结构中的各元素的操作。
嵌入式应用场景
- 设备树遍历
- AST 处理
- 报表生成
// 访问者模式 - 设备树操作#include <stdint.h>
typedef struct Node Node;typedef struct Visitor Visitor;
typedef void (*VisitFunc)(Visitor *vis, Node *node);
struct Visitor { VisitFunc visit_device; VisitFunc visit_sensor; VisitFunc visit_actuator;};
struct Node { const char *name; uint8_t type; // 0: device, 1: sensor, 2: actuator Node *children; Node *next;};
void Visitor_Visit(Visitor *vis, Node *node) { if (!node) return;
switch (node->type) { case 0: if (vis->visit_device) vis->visit_device(vis, node); break; case 1: if (vis->visit_sensor) vis->visit_sensor(vis, node); break; case 2: if (vis->visit_actuator) vis->visit_actuator(vis, node); break; }
// 访问子节点 for (Node *child = node->children; child; child = child->next) { Visitor_Visit(vis, child); }}
// 具体访问者 - 统计设备数量static uint32_t sensor_count = 0;static uint32_t actuator_count = 0;
static void count_sensor(Visitor *vis, Node *node) { sensor_count++; printf("Sensor: %s\n", node->name);}
static void count_actuator(Visitor *vis, Node *node) { actuator_count++; printf("Actuator: %s\n", node->name);}
static Visitor counter = { .visit_sensor = count_sensor, .visit_actuator = count_actuator,};4.11 解释器模式 (Interpreter)
核心思想
给定一个语言,定义它的文法的一种表示。
嵌入式应用场景
- 命令解析
- 配置脚本
- 简单协议解析
// 解释器模式 - 简单命令解析#include <stdint.h>#include <stdbool.h>
typedef struct Expression Expression;
typedef bool (*InterpretFunc)(Expression *exp, const char *context);
struct Expression { InterpretFunc interpret;};
// 终结符表达式typedef struct { Expression base; char keyword[16];} TerminalExpression;
bool terminal_interpret(Expression *exp, const char *cmd) { TerminalExpression *term = (TerminalExpression*)exp; return strncmp(cmd, term->keyword, strlen(term->keyword)) == 0;}
// 非终结符表达式 - Andtypedef struct { Expression base; Expression *left; Expression *right;} AndExpression;
bool and_interpret(Expression *exp, const char *cmd) { AndExpression *ae = (AndExpression*)exp; return ae->left->interpret(ae->left, cmd) && ae->right->interpret(ae->right, cmd);}
// 使用示例void interpreter_demo(void) { // 构建语法树: "SET" AND "LED" AND "ON" static TerminalExpression set_exp = { .base = {.interpret = terminal_interpret}, .keyword = "SET" }; static TerminalExpression led_exp = { .base = {.interpret = terminal_interpret}, .keyword = "LED" }; static TerminalExpression on_exp = { .base = {.interpret = terminal_interpret}, .keyword = "ON" };
static AndExpression and1 = { .base = {.interpret = and_interpret}, .left = &set_exp.base, .right = &led_exp.base };
static AndExpression and2 = { .base = {.interpret = and_interpret}, .left = &and1.base, .right = &on_exp.base };
bool result = and2.base.interpret(&and2.base, "SET LED ON"); printf("Result: %s\n", result ? "OK" : "FAIL");}五、嵌入式设计模式使用建议
5.1 模式选择指南
5.2 嵌入式推荐模式
| 模式 | 推荐程度 | 适用场景 | 资源开销 |
|---|---|---|---|
| 单例模式 | ⭐⭐⭐⭐⭐ | 硬件管理 | 低 |
| 工厂方法 | ⭐⭐⭐⭐⭐ | 驱动注册 | 低 |
| 观察者模式 | ⭐⭐⭐⭐⭐ | 事件系统 | 中 |
| 状态模式 | ⭐⭐⭐⭐ | 协议状态机 | 中 |
| 策略模式 | ⭐⭐⭐⭐ | 算法切换 | 低 |
| 命令模式 | ⭐⭐⭐⭐ | 任务队列 | 中 |
| 模板方法 | ⭐⭐⭐⭐ | 驱动框架 | 低 |
| 适配器模式 | ⭐⭐⭐⭐ | 驱动兼容 | 低 |
| 责任链模式 | ⭐⭐⭐ | 消息处理 | 中 |
| 外观模式 | ⭐⭐⭐ | HAL 封装 | 低 |
5.3 注意事项
1. 避免过度设计
// ❌ 过度设计class AbstractFactoryBuilderAdapter<template<T>::Strategy> {};
// ✅ 适度设计typedef struct { void (*init)(void); void (*deinit)(void);} Driver;2. 考虑资源限制
// ❌ 动态内存 (嵌入式禁忌)void *malloc(size_t size);
// ✅ 静态分配static uint8_t buffer[256];3. 优先级
六、总结
设计模式不是银弹,在嵌入式开发中需要根据实际场景和资源限制灵活运用。记住:简单的代码比聪明的代码更可靠。
参考资料:
- 《Design Patterns: Elements of Reusable Object-Oriented Software》
- 《Patterns of Enterprise Application Architecture》
- 《Embedded Systems Architecture》
Some information may be outdated