美文网首页
嵌入式开发中常用的软件设计模式(c语言实现)

嵌入式开发中常用的软件设计模式(c语言实现)

作者: qianlihu | 来源:发表于2018-09-29 19:53 被阅读420次

    软件项目各有不同,开发语言多种多样,但软件开发这种行为过程,有其规律性,很多前辈从各个角度对软件开发这种行为做了总结。我们这里来介绍GOF从工程实现的角度总结的23种设计模式(最近实践),这将会是一个系列。

    软件开发是一种智力活动,沟通交流时多有障碍,从设计模式的角度来沟通功能的实现,也能大大提高沟通效率。

    在我个人的软件开发经历中,感受最深的是命令模式和观察者模式。我们先从命令模式开始。

    先来看一个通讯协议相关的例子,数据帧定义如下:

    帧长度 传感器类型 数据
    1字节 1字节 n字节

    传感器数据格式定义如下

    传感器 类型号 数据格式
    温度传感器 整型数据(4字节)
    湿度传感器 整型数据(4字节)

    解析实现可如下实现:

    static int parse(const char *data,size_t n)
    {
        int len = data[0];
        int type = data[2];
        int value;
        switch(type){
            case 1:
                value = *(int *)&data[3];
                printf("temperatue = %d\n",value);
            case 2:
                value = *(int *)&data[3];
                printf("humidity = %d\n",value);
            default:
                printf("parse error\n");
        }
        
    }
    

    相信你已经嗅到了这段代码的坏味道,如果我们系统中要添加更多的传感器类型,势必需要向switch case 语句中增加更多的case 语句。使得parse函数越来越臃肿。

    当然,我们可以采用,如下方式规避一些问题

    static int parse_temperature(const char *data,size_t len)
    {
        assert(len == 4);
        int value = *(int *)data;
        printf("temperature = %d\n",value);
    }
    static int parse_humidity(const char *data,size_t len)
    {
        assert(len==4);
        int value = *(int *)data;
        printf("humidity = %d\n",value);
    }
    
    static void parse(const char *data,size_t len)
    {
        int data_len = data[0];
        int data_type = data[1];
        switch(type){
            case 1:
                parse_temperature(data+2,data_len-2);
                break;
            case 2:
                parse_humidity(data+2,data_len-2);
                break;
            default:
                break;
        }
    }
    

    上面的代码相比与第一次实现有所改善,但是我们采用命令模式实现后,会看到,无论是可读性,可扩展性,都会得到相当成都的提高。

    typedef int (*parse_func)(const char *data,size_t len);
    
    struct parse_handler{
        int type;
        parse_func func;
    }
    
    static int parse_temperature(const char *data,size_t len)
    {
        assert(len == 4);
        int value = *(int *)data;
        printf("temperature = %d\n",value);
    }
    static int parse_humidity(const char *data,size_t len)
    {
        assert(len==4);
        int value = *(int *)data;
        printf("humidity = %d\n",value);
    }
    
    static struct parse_handler handlers = {
        {1,parse_tmepeature},
        {2,parse_humidity},
    };
    
    #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
    static parse_func parse_func_find(int type)
    {
        int i;
        for(i=0;i<ARRAY_SIZE(handlers);i++){
            if(handlers[i].type == type)
                return handlers[i].func;
        }
        return NULL;
    }
    
    static int parse(const char *data,size_t len)
    {
        int data_len = data[0];
        int data_type = data[1];
        
        parse_func func = parse_func_find(data_type);
        if(func != NULL)
            func(data+2,data_len-2);
    }
    

    如上,需要增加或者修改传感器的时候,我们只需要关注handlers这个数组。

    static struct parse_handler handlers = {
        {1,parse_tmepeature},
        {2,parse_humidity},
    };
    

    这样写的优势

    • 传感器类型和解析实现直接写在了同一行,非常直观,也没有必要将传感器类型数据定义为宏。
    • 添加传感器的时候,只要在结构体数组中添加一行即可,如果是第二种实现,则需要在parse函数中,添加一个case语句,若是遗忘了break很容易导致错误。

    这种实现方式,基本是此类问题的最优解。被称为命令模式。一个type被称为一个命令,解析函数对应于命令的实现。

    很多命令行工具都是采用的此类实现方式。伪代码如下:

    char buffer[1024];
    while(true){
        char *p = fgets(buffer,sizeof(buffer),stdin);
        execute(p) //执行某个命令,先find再执行。
    }
    

    相关文章

      网友评论

          本文标题:嵌入式开发中常用的软件设计模式(c语言实现)

          本文链接:https://www.haomeiwen.com/subject/xjiboftx.html