嵌入式软件设计模式 好文值得收藏

描述

本文引用自本人公众号文章:

嵌入式开发中的两点编程思想
 

C语言也很讲究设计模式?一文讲透
 

包含如下:

01)C语言和设计模式(继承、封装、多态)

 

02)C语言和设计模式(访问者模式)

 

03)C语言和设计模式(状态模式)

 

04)C语言和设计模式(命令模式)

 

05)C语言和设计模式(解释器模式)

 

06)C语言和设计模式(备忘录模式)

 

07)C语言和设计模式(观察者模式)

 

08)C语言和设计模式(桥接模式)

 

09)C语言和设计模式(建造者模式)

 

10)C语言和设计模式(中介者模式)

 

11)C语言和设计模式(策略模式)

 

12)C语言和设计模式(适配器模式)

 

13)C语言和设计模式(装饰模式)

 

14)C语言和设计模式(享元模式)

 

15)C语言和设计模式(代理模式)

 

16)C语言和设计模式(外观模式)

 

17)C语言和设计模式(迭代器模式)

 

18)C语言和设计模式(抽象工厂模式)

 

19)C语言和设计模式(责任链模式)

 

20)C语言和设计模式(工厂模式)

 

21)C语言和设计模式(模板模式)

 

22)C语言和设计模式(组合模式)

 

23)C语言和设计模式(原型模式)

 

24)C语言和设计模式(单件模式)

 

25)C语言和设计模式(开篇)

-----------------------
01)C语言和设计模式(继承、封装、多态)
 

   记得还在我们大学C++第一门课的时候,老师就告诉我们说,C++是一门面向对象的语言。C++有三个最重要的特点,即继承、封装、多态。等到后来随着编码的增多和工作经验的积累,我也慢慢明白了面向对象的含义。可是,等我工作以后,使用的编程语言更多的是C语言,这时候我又想能不能把C语言变成面向对象的语言呢?等到后来通过思考和实践,我发现其实C语言也是可以面向对象的,也是可以应用设计模式的,关键就在于如何实现面向对象语言的三个重要属性。
(1)继承性
typedef struct _parent
{
    int data_parent;
 
}Parent;
 
typedef struct _Child
{
    struct _parent parent;
    int data_child;
 
}Child;
    在设计C语言继承性的时候,我们需要做的就是把基础数据放在继承的结构的首位置即可。这样,不管是数据的访问、数据的强转、数据的访问都不会有什么问题。
 
(2)封装性
struct _Data;
 
typedef  void (*process)(struct _Data* pData);
 
typedef struct _Data
{
    int value;
    process pProcess;
    
}Data;
    封装性的意义在于,函数和数据是绑在一起的,数据和数据是绑在一起的。这样,我们就可以通过简单的一个结构指针访问到所有的数据,遍历所有的函数。封装性,这是类拥有的属性,当然也是数据结构体拥有的属性。
 
(3)多态
typedef struct _Play
{
    void* pData;
    void (*start_play)(struct _Play* pPlay);
}Play;
    多态,就是说用同一的接口代码处理不同的数据。比如说,这里的Play结构就是一个通用的数据结构,我们也不清楚pData是什么数据,start_play是什么处理函数?但是,我们处理的时候只要调用pPlay->start_play(pPlay)就可以了。剩下来的事情我们不需要管,因为不同的接口会有不同的函数去处理,我们只要学会调用就可以了。

-----------------------

02)C语言和设计模式(访问者模式)


不知不觉当中,我们就到了最后一种设计模式,即访问者模式。访问者模式,听上去复杂一些。但是,这种模式用简单的一句话说,就是不同的人对不同的事物有不同的感觉。比如说吧,豆腐可以做成麻辣豆腐,也可以做成臭豆腐。可是,不同的地方的人未必都喜欢这两种豆腐。四川的朋友可能更喜欢辣豆腐,江浙的人就可能对臭豆腐更喜欢一些。那么,这种情况应该怎么用设计模式表达呢?
 
typedef struct _Tofu
{
    int type;
    void (*eat) (struct _Visitor* pVisitor, struct _Tofu* pTofu);
}Tofu;
 
typedef struct _Visitor
{
    int region;
    void (*process)(struct _Tofu* pTofu, struct _Visitor* pVisitor);
}Visitor;
    就是这样一个豆腐,eat的时候就要做不同的判断了。
void eat(struct _Visitor* pVisitor, struct _Tofu* pTofu)
{
    assert(NULL != pVisitor && NULL != pTofu);
 
    pVisitor->process(pTofu, pVisitor);
}
    既然eat的操作最后还是靠不同的visitor来处理了,那么下面就该定义process函数了。
void process(struct _Tofu* pTofu, struct _Visitor* pVisitor)
{
    assert(NULL != pTofu && NULL != pVisitor);
 
    if(pTofu->type == SPICY_FOOD && pVisitor->region == WEST ||
        pTofu->type == STRONG_SMELL_FOOD && pVisitor->region == EAST)
    {
        printf("I like this food!\n");
        return;
    }
 
    printf("I hate this food!\n");   
}

-----------------------------------------------------

03)C语言和设计模式(状态模式)

  状态模式是协议交互中使用得比较多的模式。比如说,在不同的协议中,都会存在启动、保持、中止等基本状态。那么怎么灵活地转变这些状态就是我们需要考虑的事情。假设现在有一个state,
 
typedef struct _State
{
    void (*process)();
    struct _State* (*change_state)();
 
}State;
   说明一下,这里定义了两个变量,分别process函数和change_state函数。其中proces函数就是普通的数据操作,
void normal_process()
{
    printf("normal process!\n");
}  
  change_state函数本质上就是确定下一个状态是什么。
struct _State* change_state()
{
    State* pNextState = NULL;
 
    pNextState = (struct _State*)malloc(sizeof(struct _State));
    assert(NULL != pNextState);
 
    pNextState ->process = next_process;
    pNextState ->change_state = next_change_state;
    return pNextState;
}
   所以,在context中,应该有一个state变量,还应该有一个state变换函数。
typedef struct _Context
{
    State* pState;
    void (*change)(struct _Context* pContext);
    
}Context;
 
void context_change(struct _Context* pContext)
{
    State* pPre;
    assert(NULL != pContext);
 
    pPre = pContext->pState;
    pContext->pState = pPre->changeState();
    free(pPre);
    return;   
}
 
 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分