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语言设计模式——命令模式相关推荐

  1. C语言实现设计模式—命令模式

    文章目录 C语言设计模式--命令模式 传统的实现方式如下:(伪代码) 命令模式优化 UML 用例说明 实现流程 command.h command.c main 总结 C语言设计模式--命令模式 好处 ...

  2. Python设计模式-命令模式

    Python设计模式-命令模式 代码基于3.5.2,代码如下; #coding:utf-8 #命令模式class barbecuer():def bakeButton(self):print(&quo ...

  3. 设计模式 命令模式 实例_根据您的命令-命令设计模式

    设计模式 命令模式 实例 命令设计模式是一种广为人知的设计模式,属于行为设计模式("四人帮"的一部分). 顾名思义,它与应用程序中的动作和事件有关. 问题陈述: 假设有一个网页将在 ...

  4. 游戏设计模式 - 命令模式在Unity中的应用(C#)

    游戏设计模式 - 命令模式在Unity中的应用(C#) 实测:这是一篇简单易懂的文章-> https://zhuanlan.zhihu.com/p/46937284

  5. C++设计模式——命令模式(command pattern)

    一.原理讲解 别名动作(action),事务(transaction). 1.1意图 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作 ...

  6. 设计模式的C语言应用-命令模式-第五章

    模式介绍:命令模式(command) 命令模式的解释如下: 向对象发送一个请求,但是并不知道该请求的具体接收者是谁,具体的处理过程是如何的,只知道在程序运行中指定具体的请求接收者即可,对于这样将请求封 ...

  7. 【知识分享】C语言中的设计模式——命令模式

    背景     命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式.请求以命令的形式包裹在对象中,并传给调用对象.调用对象寻找可以处理该命令的合适的对象,并把该命令传给 ...

  8. 游戏设计模式---命令模式

    命令模式 游戏设计模式Design Patterns Revisited 命令模式是我最喜欢的模式之一. 大多数我写的游戏或者别的什么之类的大型程序,都会在某处用到它. 当在正确的地方使用时,它可以将 ...

  9. [Head First设计模式]餐馆中的设计模式——命令模式

    系列文章 [Head First设计模式]山西面馆中的设计模式--装饰者模式 [Head First设计模式]山西面馆中的设计模式--观察者模式 [Head First设计模式]山西面馆中的设计模式- ...

最新文章

  1. 用单片机测量流体流速的_流量计是测量液体、气体流量仪表原理安装
  2. 百分点宣布完成C轮融资2500万美元 将进一步开放云平台应用
  3. esp8266接收到的数据如何存放到数组中_愉快地学Java语言:第七章 数组
  4. 【转载】 C++中回车换行(\n\r)和换行(\r)的区别
  5. 现代软件工程讲义 4 团队和流程
  6. Mac上的IDEA安装配置maven
  7. php输出字符unicode码,PHP解码unicode编码的中文字符代码分享
  8. Windows核心编程MFC_gdi+发光字
  9. Docker教程:dokcer的配置和命令
  10. python 除法 保留2位小数
  11. Linux 之CentOS7-VSFTP搭建
  12. Audio播放流程(一)---MediaPlayer流程
  13. java项目笔记 - 第18章:坦克大战2.1
  14. Least Angel Regression
  15. 2021年最佳Linux发行版推荐列表
  16. sql server数据库练习
  17. 现代OpenGL教程 02——贴图
  18. 024 | 知行国学:全国领先的线上一对一国学教育平台 | 大学生创新训练项目申请书 | 极致技术工厂
  19. DOTA数据集测试mAP
  20. AirSim动态 | 安装配置AirSim环境(一)

热门文章

  1. iphone-common-codes-ccteam源代码 CCNSArray.h
  2. 2010-04-25 搞定aftr
  3. 39--打印从1到最大的n位数
  4. loading gif 透明_搞笑GIF:有这样的女朋友下班哪里都不想去
  5. 【机器学习】feature_importances_ 参数源码解析
  6. 智能外呼系统相关资料总结
  7. python实参_python的形参和实参
  8. 数字信号处理的fpga实现_FPGA数字信号处理:通信类I/Q信号及产生
  9. visuall assist x 破解方法
  10. access 根据id删除数据_小程序云开发之数据库自动备份丨云开发101