桥接模式定义
桥接模式是结构型设计模式 的一种,核心思想是:将「抽象部分」与「实现部分」解耦,使两者可以独立变化,通过「组合」而非「继承」的方式建立两个维度的关联,避免因多层继承导致的类爆炸问题。
简单来说:桥接模式的本质是 "拆维度、解耦合"------ 把一个复杂系统拆解为两个或多个独立变化的维度,每个维度单独扩展,维度间通过 "桥"(引用 / 组合)关联。
场景理解
一、场景背景
- 硬件:STM32 开发板,支持 串口、CAN1等多种通信外设;
- 协议:
- 协议 A:简单串口协议(帧格式:
0xAA + 命令 + 参数 + 0x55); - 协议 B:CAN 专用协议(帧格式:标准 ID=0x123 + 命令 + 参数 + 校验位);
- 协议 A:简单串口协议(帧格式:
- 需求:开发板能通过「串口 + 协议 A」「CAN + 协议 B」通信,后续可能CAN + 协议A或串口+协议B,也是有可能。
二、不用桥接模式
如果直接写死逻辑,会出现:
// 耦合严重的写法:通信方式和协议绑死
void send_data_usart_a(uint8_t cmd, uint8_t param) {
// 串口+协议A的发送逻辑
uint8_t buf[] = {0xAA, cmd, param, 0x55};
HAL_UART_Transmit(&huart1, buf, 4, 100);
}
void send_data_can_b(uint8_t cmd, uint8_t param) {
// CAN+协议B的发送逻辑
CanTxMsg msg = {.StdId=0x123, .DLC=3, .Data={cmd, param, cmd^param}};
HAL_CAN_Transmit(&hcan1, &msg, 100);
}
问题:新增「串口 + 协议 B」或「CAN + 协议 A」,要重写大量重复代码;改协议格式,所有通信方式的代码都要改。
三、桥接模式实现(拆维度、解耦合)
核心思路:拆成两个独立维度
| 维度 | 职责 | 具体实现 |
|---|---|---|
| 实现维度(通信硬件) | 底层硬件收发(串口 / CAN),屏蔽硬件差异 | 串口驱动、CAN 驱动 |
| 抽象维度(通信协议) | 协议编解码(协议 A / 协议 B),屏蔽协议差异 | 协议 A 解析、协议 B 解析 |
| 桥接 | 协议对象持有通信驱动引用,通过组合调用 | 协议 A 对象→串口驱动 |
四、代码实现
结构体元素:
1、基础的硬件接口初始化函数init
2、发送函数send+接收函数recv
3、回调函数表,什么命令触发什么回调函数
4、解析接受数据的函数
typedef struct {
// 1. 硬件接口初始化函数
CommStatus (*init)(void);
// 2. 发送/接收函数
CommStatus (*send)(const uint8_t *data, uint16_t len);
CommStatus (*recv)(uint8_t *data, uint16_t max_len, uint16_t *recv_len);
// 3. 回调函数表(命令-回调映射)
const CmdCallbackItem *cb_table;
uint16_t cb_table_len; // 回调表长度
// 4. 解析接收数据的函数
CmdType (*parse)(const uint8_t *data, uint16_t len, uint8_t *param);
} CommProto;
流程:
1、主函数完成init,如何轮询等待接收,如果有数据,则将数据和对应的长度传递至parse中
2、parse中对数据进行校验判断,判断成功后,根据命令去回调函数并调用send回应主机