C语言设计模式——命令模式
C语言设计模式——命令模式
好处:让代码清晰明了,容易添加和删除,易维护。
哪些地方会用到命令模式?(列出几个常见的例子)
1、按键处理,每个按键按下得到一个索引(指的就是命令),一个按键对应一个处理函数。按键处理命令模式
2、协议解析(串口,网口,CAN,等等);以串口为例简单说明一下,比如有如下协议:http类型解析(html,jpg,jpeg...)
帧头 | 命令 | 数据长度 | 数据内容 | 校验 | 帧尾 |
1字节 | 1字节 | 2字节 | n字节 | 2字节 | 1字节 |
命令1:0x01 温度
命令2:0x02 湿度
命令3:0x03 光照强度
传统的实现方式如下:(伪代码)
static uint8_t parse(char *buffer, uint16_t length)
{uint8_t head = buffer[0];uint8_t cmd = buffer[1];uint16_t len = (buffer[2] << 8) | buffer[3];uint16_t crc = CRCCheck(buffer, length - 3);uint8_t tail = buffer[length - 1];if((head != xxx) && (tail != xxx) && (crc != ((buffer[length - 3]) << 8) | buffer[length - 2])){return 0;}switch(cmd){case 0x01:int temperatue = *(int *)&buffer[4];printf("temperatue = %d\n", temperatue);break;case 0x02:int humidity = *(int *)&buffer[4];printf("humidity = %d\n", humidity);break;case 0x03:int illumination= *(int *)&buffer[4];printf("illumination = %d\n", illumination);break;default:printf("parse error\n");break;}return 1;
}
通过这段伪代码可以看出代码结构的一些问题,如果要添加更多的命令,势必需要向switch case语句中加入更多的case语句。使得解析函数越来越臃肿。当然我们可以使用如下方式规避一些问题:(伪代码)
// 当心字节对齐的问题
typedef struct
{uint8_t head;uint8_t cmd;uint16_t length;uint8_t data[1];
} package_t;static int parse_temperature(char *buffer)
{int value = *(int *)buffer;printf("temperature = %d\n", value);
}
static int parse_humidity(char *buffer)
{int value = *(int *)buffer;printf("humidity = %d\n", value);
}static int parse_illumination(char *buffer)
{int value = *(int *)buffer;printf("illumination = %d\n", value);
}static uint8_t parse(char *buffer, uint16_t length)
{package_t *frame = (package_t *)buffer;uint16_t crc = CRCCheck(buffer, length - 3);uint8_t tail = buffer[length - 1];if((frame->head != xxx) && (tail != xxx) && (crc != (buffer[length - 3]) << 8 | buffer[length - 2])){return 0;}switch(frame->cmd){case 0x01:parse_temperature(frame->data);break;case 0x02:parse_humidity(frame->data);break;case 0x03:parse_illumination(frame->data);break;default:printf("parse error\n");}return 1;
}
相比于第一段代码,已经有了很大的改善,扩展性也得到了很大的提升。随着项目的进行,解析函数还是可能会越来越大。接下来就开始介绍命令模式。在命令模式里面,我们只需要维护一个命令列表就行了,而不需要关注解析函数本身。(伪代码)
// 当心字节对齐的问题
typedef struct
{uint8_t head;uint8_t cmd;uint16_t length;uint8_t data[1];
} package_t;static int parse_temperature(char *buffer)
{int value = *(int *)buffer;printf("temperature = %d\n", value);
}
static int parse_humidity(char *buffer)
{int value = *(int *)buffer;printf("humidity = %d\n", value);
}static int parse_illumination(char *buffer)
{int value = *(int *)buffer;printf("illumination = %d\n", value);
}typedef struct
{uint8_t cmd;void (* handle)(char *buffer);
} package_entry_t;static const package_entry_t package_items[] =
{{0x01, parse_temperature},{0x02, parse_humidity},{0x03, parse_illumination},{0xFF, NULL},
};static uint8_t parse(char *buffer, uint16_t length)
{package_t *frame = (package_t *)buffer;uint16_t crc = CRCCheck(buffer, length - 3);uint8_t tail = buffer[length - 1];const package_entry_t *entry;if((frame->head != xxx) && (tail != xxx) && (crc != (buffer[length - 3]) << 8 | buffer[length - 2])){return 0;}for(entry = package_items; entry->handle != NULL; ++entry){if(frame->cmd == entry->cmd){entry->handle(frame->data);break;}}return 1;
}
我们可以看到,解析函数写好之后就不用动了,需要变化的只是一个表。这样写能让代码看起来干净整洁清晰,命令也可以使用宏定义或者枚举,看自己的喜好吧。一个命令对应一个处理函数,尽量使用此类方式去取代swicth case的方式,始终让代码保持整洁易扩展易维护的特性。
上面使用了命令模式作用于串口协议,同样的方式可以适用于各种协议,网口协议的话,格式都不用改。如果是can协议的话,将can的id用作命令,就ok了。其他的,类似。
C语言设计模式——命令模式相关推荐
- C语言实现设计模式—命令模式
文章目录 C语言设计模式--命令模式 传统的实现方式如下:(伪代码) 命令模式优化 UML 用例说明 实现流程 command.h command.c main 总结 C语言设计模式--命令模式 好处 ...
- Python设计模式-命令模式
Python设计模式-命令模式 代码基于3.5.2,代码如下; #coding:utf-8 #命令模式class barbecuer():def bakeButton(self):print(&quo ...
- 设计模式 命令模式 实例_根据您的命令-命令设计模式
设计模式 命令模式 实例 命令设计模式是一种广为人知的设计模式,属于行为设计模式("四人帮"的一部分). 顾名思义,它与应用程序中的动作和事件有关. 问题陈述: 假设有一个网页将在 ...
- 游戏设计模式 - 命令模式在Unity中的应用(C#)
游戏设计模式 - 命令模式在Unity中的应用(C#) 实测:这是一篇简单易懂的文章-> https://zhuanlan.zhihu.com/p/46937284
- C++设计模式——命令模式(command pattern)
一.原理讲解 别名动作(action),事务(transaction). 1.1意图 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作 ...
- 设计模式的C语言应用-命令模式-第五章
模式介绍:命令模式(command) 命令模式的解释如下: 向对象发送一个请求,但是并不知道该请求的具体接收者是谁,具体的处理过程是如何的,只知道在程序运行中指定具体的请求接收者即可,对于这样将请求封 ...
- 【知识分享】C语言中的设计模式——命令模式
背景 命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式.请求以命令的形式包裹在对象中,并传给调用对象.调用对象寻找可以处理该命令的合适的对象,并把该命令传给 ...
- 游戏设计模式---命令模式
命令模式 游戏设计模式Design Patterns Revisited 命令模式是我最喜欢的模式之一. 大多数我写的游戏或者别的什么之类的大型程序,都会在某处用到它. 当在正确的地方使用时,它可以将 ...
- [Head First设计模式]餐馆中的设计模式——命令模式
系列文章 [Head First设计模式]山西面馆中的设计模式--装饰者模式 [Head First设计模式]山西面馆中的设计模式--观察者模式 [Head First设计模式]山西面馆中的设计模式- ...
最新文章
- 用单片机测量流体流速的_流量计是测量液体、气体流量仪表原理安装
- 百分点宣布完成C轮融资2500万美元 将进一步开放云平台应用
- esp8266接收到的数据如何存放到数组中_愉快地学Java语言:第七章 数组
- 【转载】 C++中回车换行(\n\r)和换行(\r)的区别
- 现代软件工程讲义 4 团队和流程
- Mac上的IDEA安装配置maven
- php输出字符unicode码,PHP解码unicode编码的中文字符代码分享
- Windows核心编程MFC_gdi+发光字
- Docker教程:dokcer的配置和命令
- python 除法 保留2位小数
- Linux 之CentOS7-VSFTP搭建
- Audio播放流程(一)---MediaPlayer流程
- java项目笔记 - 第18章:坦克大战2.1
- Least Angel Regression
- 2021年最佳Linux发行版推荐列表
- sql server数据库练习
- 现代OpenGL教程 02——贴图
- 024 | 知行国学:全国领先的线上一对一国学教育平台 | 大学生创新训练项目申请书 | 极致技术工厂
- DOTA数据集测试mAP
- AirSim动态 | 安装配置AirSim环境(一)
热门文章
- iphone-common-codes-ccteam源代码 CCNSArray.h
- 2010-04-25 搞定aftr
- 39--打印从1到最大的n位数
- loading gif 透明_搞笑GIF:有这样的女朋友下班哪里都不想去
- 【机器学习】feature_importances_ 参数源码解析
- 智能外呼系统相关资料总结
- python实参_python的形参和实参
- 数字信号处理的fpga实现_FPGA数字信号处理:通信类I/Q信号及产生
- visuall assist x 破解方法
- access 根据id删除数据_小程序云开发之数据库自动备份丨云开发101