1. 什么是命令模式?
命令模式是一种行为型设计模式,它将请求封装成对象,使发出请求的对象和执行请求的对象解耦。这种模式支持可撤销的操作,并能实现请求的排队和日志记录。
2. 为什么需要命令模式?
- 将请求发送者和接收者解耦
- 支持命令的排队执行
- 支持可撤销操作
- 方便添加新的命令
- 实现请求的日志记录
3. 实际应用场景
- 嵌入式系统命令处理
- 串口通信协议解析
- 设备控制命令管理
- 多级菜单系统
- 工业控制系统
代码实现
4.1 UML 关系图
4.2 头文件 (command.h)
#ifndef COMMAND_H
#define COMMAND_H
#include <stdint.h>
#include <stdbool.h>
// 命令结构体
typedef struct {
uint8_t* data;
uint16_t length;
} command_t;
// 命令处理函数指针
typedef bool (*command_handler_t)(command_t* cmd);
// 命令包条目
typedef struct {
uint8_t cmd; // 命令ID
command_handler_t handler; // 处理函数
const char* description; // 命令描述
} command_package_entry_t;
// 命令解析函数
bool command_parse(command_t* cmd, uint8_t cmd_type);
#endif // COMMAND_H
4.3 实现文件 (command.c)
#include "command.h"
#include <stdio.h>
#include <string.h>
// LED控制命令处理
static bool handle_led_control(command_t* cmd) {
if (cmd->length < 2) return false;
uint8_t led_id = cmd->data[0];
uint8_t led_state = cmd->data[1];
printf("LED[%d] 设置为: %s\n", led_id, led_state ? "开" : "关");
return true;
}
// 电机控制命令处理
static bool handle_motor_control(command_t* cmd) {
if (cmd->length < 3) return false;
uint8_t motor_id = cmd->data[0];
uint8_t direction = cmd->data[1];
uint8_t speed = cmd->data[2];
printf("电机[%d] 方向: %d, 速度: %d\n", motor_id, direction, speed);
return true;
}
// 传感器数据读取命令处理
static bool handle_sensor_read(command_t* cmd) {
if (cmd->length < 1) return false;
uint8_t sensor_id = cmd->data[0];
printf("读取传感器[%d]数据\n", sensor_id);
return true;
}
// 命令包表
static const command_package_entry_t package_items[] = {
{0x01, handle_led_control, "LED控制命令"},
{0x02, handle_motor_control, "电机控制命令"},
{0x03, handle_sensor_read, "传感器读取命令"},
{0xFF, NULL, NULL} // 结束标记
};
bool command_parse(command_t* cmd, uint8_t cmd_type) {
if (!cmd || !cmd->data) return false;
for(uint8_t i = 0; package_items[i].handler != NULL; i++) {
if(cmd_type == package_items[i].cmd) {
printf("执行命令: %s\n", package_items[i].description);
return package_items[i].handler(cmd);
}
}
printf("未知命令类型: 0x%02X\n", cmd_type);
return false;
}
4.4 使用示例 (main.c)
#include "command.h"
#include <stdio.h>
int main() {
// LED控制命令测试
uint8_t led_data[] = {0x01, 0x01}; // LED1 打开
command_t led_cmd = {
.data = led_data,
.length = sizeof(led_data)
};
command_parse(&led_cmd, 0x01);
// 电机控制命令测试
uint8_t motor_data[] = {0x02, 0x01, 0x64}; // 电机2,正转,速度100
command_t motor_cmd = {
.data = motor_data,
.length = sizeof(motor_data)
};
command_parse(&motor_cmd, 0x02);
return 0;
}
5. 代码分析
5.1 关键设计点
- 命令接口统一
- 命令处理函数表
- 命令参数封装
- 错误处理机制
5.2 实现特点
- 使用函数指针实现命令处理
- 静态命令表管理
- 命令参数检查
- 支持命令描述
6. 编译和运行
gcc -c command.c -o command.o
gcc -c main.c -o main.o
gcc command.o main.o -o program
7. 注意事项
- 命令参数长度检查
- 命令类型有效性验证
- 内存管理安全
- 错误处理完整性
8. 改进建议
- 添加命令队列机制
- 实现命令日志记录
- 添加命令超时处理
- 支持命令响应机制
9. 总结
命令模式通过将请求封装成对象,实现了请求发送者和接收者的解耦。这种模式特别适合需要处理多种命令的系统,具有良好的扩展性和维护性。
参考资料
- 《设计模式:可复用面向对象软件的基础》
- 《C语言程序设计》
- 《嵌入式系统设计》