首页 > 编程知识 正文

C++设计模式有哪些,c语言设计模式实战

时间:2023-05-04 11:14:13 阅读:260048 作者:2304

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

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 = %dn", temperatue); break; case 0x02: int humidity = *(int *)&buffer[4]; printf("humidity = %dn", humidity); break; case 0x03: int illumination= *(int *)&buffer[4]; printf("illumination = %dn", illumination); break; default: printf("parse errorn"); break; } return 1;}

通过这段伪代码可以看出代码结构的一些问题,如果要添加更多的命令,势必需要向switch case语句中加入更多的case语句。使得解析函数越来越臃肿。当然我们可以使用如下方式规避一些问题:(伪代码)

命令模式优化

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
优点: 1、降低了系统耦合度。 2、新的命令可以很容易添加到系统中去。
缺点:使用命令模式可能会导致某些系统有过多的具体命令类。
使用场景:认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟 CMD。

UML 用例说明

实现流程

C语言实现的命令模式核心数据结构是命令。发布命令的是invoker,多个invoker将命令封装起来,送到队列里。有一个函数或者线程称为receiver,检查队列里是否有没有处理的命令。由receiver负责调用各个handler。另外一个被经常使用的辅助数据结构是命令码数组,在如果invoker和handler运行于不同的环境,这种做法几乎是必选,如核间通信,内核和应用态通信。命令码作为索引,handler调用函数作为元素,Receiver根据不同的命令码调用handler。

command.h #ifndef __COMMAND_H#define __COMMAND_H#include <rtthread.h>#include "lw_oopc.h"#include <stdbool.h>typedef struct rz_command_t rz_command_t;typedef struct rz_command_param_def{ uint8_t head; uint8_t cmd; uint16_t length; uint8_t* data;}rz_command_param_t;typedef struct rz_command_package_entry_def{ uint8_t cmd; bool (* handle)(rz_command_t * t);} rz_command_package_entry_t;CLASS(rz_command_t){char *name; rz_command_param_t param; bool (*rz_command_parse)(rz_command_t * pobj, int cmd); void (*init)(rz_command_t * pobj);};void rz_command_obj_init(void);rz_command_t * rz_command_obj_get(void);#endif command.c #include "Command.h" static rz_command_t rz_command_obj;rz_command_t * rz_command_obj_get(void){ return (rz_command_t *)&rz_command_obj;}static bool parse_temperature(rz_command_t * t){ rt_kprintf("%srn", __FUNCTION__);return true;}static bool parse_humidity(rz_command_t * t){rt_kprintf("%srn", __FUNCTION__);return true;} static bool parse_illumination(rz_command_t * t){ rt_kprintf("%srn", __FUNCTION__);return true;}static const rz_command_package_entry_t package_items[] ={ {0x01, parse_temperature}, {0x02, parse_humidity}, {0x03, parse_illumination}, {0xFF, NULL},};bool rz_command_parse(rz_command_t * pobj, int cmd){for(uint8_t i = 0; i < sizeof(package_items)/sizeof(package_items[0]); i++){if((cmd == package_items[i].cmd) && (NULL != package_items[i].handle)){ if(true == package_items[i].handle(pobj)){return true;}}} return false;}static void command_init(rz_command_t *t){t->name = "Command";}void rz_command_obj_init(void){ rz_command_t * polt = rz_command_obj_get(); rz_command_t_ctor(polt); polt->init(polt);}CTOR(rz_command_t)FUNCTION_SETTING(rz_command_parse, rz_command_parse);FUNCTION_SETTING(init, command_init);END_CTOR main int Command(void){ rt_uint8_t count; rz_command_obj_init(); rz_command_t * pobj = rz_command_obj_get(); for(count = 0 ; count < 3 ;count++){ pobj->rz_command_parse(pobj,count);rt_thread_mdelay(100);} return 0;}MSH_CMD_EXPORT(Command, RT-Thread first Command sample); 总结 在命令模式中,将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作模式或事务模式。命令模式的主要优点在于降低系统的耦合度,增加新的命令很方便,而且可以比较容易地设计一个命令队列和宏命令,并方便地实现对请求的撤销和恢复;其主要缺点在于可能会导致某些系统有过多的具体命令类。命令模式适用情况包括:需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互;需要将一组操作组合在一起,即支持宏命令。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。