C语言设计模式.docx

上传人:b****8 文档编号:13073862 上传时间:2023-06-10 格式:DOCX 页数:54 大小:35.86KB
下载 相关 举报
C语言设计模式.docx_第1页
第1页 / 共54页
C语言设计模式.docx_第2页
第2页 / 共54页
C语言设计模式.docx_第3页
第3页 / 共54页
C语言设计模式.docx_第4页
第4页 / 共54页
C语言设计模式.docx_第5页
第5页 / 共54页
C语言设计模式.docx_第6页
第6页 / 共54页
C语言设计模式.docx_第7页
第7页 / 共54页
C语言设计模式.docx_第8页
第8页 / 共54页
C语言设计模式.docx_第9页
第9页 / 共54页
C语言设计模式.docx_第10页
第10页 / 共54页
C语言设计模式.docx_第11页
第11页 / 共54页
C语言设计模式.docx_第12页
第12页 / 共54页
C语言设计模式.docx_第13页
第13页 / 共54页
C语言设计模式.docx_第14页
第14页 / 共54页
C语言设计模式.docx_第15页
第15页 / 共54页
C语言设计模式.docx_第16页
第16页 / 共54页
C语言设计模式.docx_第17页
第17页 / 共54页
C语言设计模式.docx_第18页
第18页 / 共54页
C语言设计模式.docx_第19页
第19页 / 共54页
C语言设计模式.docx_第20页
第20页 / 共54页
亲,该文档总共54页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

C语言设计模式.docx

《C语言设计模式.docx》由会员分享,可在线阅读,更多相关《C语言设计模式.docx(54页珍藏版)》请在冰点文库上搜索。

C语言设计模式.docx

C语言设计模式

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

C++有三个最重要的特点,即继承、封装、多态。

我发现其实C语言也是可以面向对象的,也是可以应用设计模式的,关键就在于如何实现面向对象语言的三个重要属性。

(1)继承性

[cpp] viewplaincopy

1.typedef struct _parent  

2.{  

3.    int data_parent;  

4.  

5.}Parent;  

6.  

7.typedef struct _Child  

8.{  

9.    struct _parent parent;  

10.    int data_child;  

11.  

12.}Child;  

  在设计C语言继承性的时候,我们需要做的就是把基础数据放在继承的结构的首位置即可。

这样,不管是数据的访问、数据的强转、数据的访问都不会有什么问题。

(2)封装性

[cpp] viewplaincopy

1.struct _Data;  

2.  

3.typedef  void (*process)(struct _Data* pData);  

4.  

5.typedef struct _Data  

6.{  

7.    int value;  

8.    process pProcess;  

9.      

10.}Data;  

  封装性的意义在于,函数和数据是绑在一起的,数据和数据是绑在一起的。

这样,我们就可以通过简单的一个结构指针访问到所有的数据,遍历所有的函数。

封装性,这是类拥有的属性,当然也是数据结构体拥有的属性。

(3)多态

[cpp] viewplaincopy

1.typedef struct _Play  

2.{  

3.    void* pData;  

4.    void (*start_play)(struct _Play* pPlay);  

5.}Play;  

  多态,就是说用同一的接口代码处理不同的数据。

比如说,这里的Play结构就是一个通用的数据结构,我们也不清楚pData是什么数据,start_play是什么处理函数?

但是,我们处理的时候只要调用pPlay->start_play(pPlay)就可以了。

剩下来的事情我们不需要管,因为不同的接口会有不同的函数去处理,我们只要学会调用就可以了。

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

不知不觉当中,我们就到了最后一种设计模式,即访问者模式。

访问者模式,听上去复杂一些。

但是,这种模式用简单的一句话说,就是不同的人对不同的事物有不同的感觉。

比如说吧,豆腐可以做成麻辣豆腐,也可以做成臭豆腐。

可是,不同的地方的人未必都喜欢这两种豆腐。

四川的朋友可能更喜欢辣豆腐,江浙的人就可能对臭豆腐更喜欢一些。

那么,这种情况应该怎么用设计模式表达呢?

[cpp] viewplaincopy

1.typedef struct _Tofu  

2.{  

3.    int type;  

4.    void (*eat) (struct _Visitor* pVisitor, struct _Tofu* pTofu);  

5.}Tofu;  

6.  

7.typedef struct _Visitor  

8.{  

9.    int region;  

10.    void (*process)(struct _Tofu* pTofu, struct _Visitor* pVisitor);  

11.}Visitor;  

  就是这样一个豆腐,eat的时候就要做不同的判断了。

[cpp] viewplaincopy

1.void eat(struct _Visitor* pVisitor, struct _Tofu* pTofu)  

2.{  

3.    assert(NULL !

= pVisitor && NULL !

= pTofu);  

4.  

5.    pVisitor->process(pTofu, pVisitor);  

6.}  

  既然eat的操作最后还是靠不同的visitor来处理了,那么下面就该定义process函数了。

[cpp] viewplaincopy

1.void process(struct _Tofu* pTofu, struct _Visitor* pVisitor)  

2.{  

3.    assert(NULL !

= pTofu && NULL !

= pVisitor);  

4.  

5.    if(pTofu->type == SPICY_FOOD && pVisitor->region == WEST ||  

6.        pTofu->type == STRONG_SMELL_FOOD && pVisitor->region == EAST)  

7.    {  

8.        printf("I like this food!

\n");  

9.        return;  

10.    }  

11.  

12.    printf("I hate this food!

\n");     

13.}  

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

  状态模式是协议交互中使用得比较多的模式。

比如说,在不同的协议中,都会存在启动、保持、中止等基本状态。

那么怎么灵活地转变这些状态就是我们需要考虑的事情。

假设现在有一个state,

[cpp] viewplaincopy

1.typedef struct _State  

2.{  

3.    void (*process)();  

4.    struct _State* (*change_state)();  

5.  

6.}State;  

  说明一下,这里定义了两个变量,分别process函数和change_state函数。

其中proces函数就是普通的数据操作,

[cpp] viewplaincopy

1.void normal_process()  

2.{  

3.    printf("normal process!

\n");  

4.}    

 change_state函数本质上就是确定下一个状态是什么。

[cpp] viewplaincopy

1.struct _State* change_state()  

2.{  

3.    State* pNextState = NULL;  

4.  

5.    pNextState = (struct _State*)malloc(sizeof(struct _State));  

6.    assert(NULL !

= pNextState);  

7.  

8.    pNextState ->process = next_process;  

9.    pNextState ->change_state = next_change_state;  

10.    return pNextState;  

11.}  

  所以,在context中,应该有一个state变量,还应该有一个state变换函数。

[cpp] viewplaincopy

1.typedef struct _Context  

2.{  

3.    State* pState;  

4.    void (*change)(struct _Context* pContext);  

5.      

6.}Context;  

7.  

8.void context_change(struct _Context* pContext)  

9.{  

10.    State* pPre;  

11.    assert(NULL !

= pContext);  

12.  

13.    pPre = pContext->pState;  

14.    pContext->pState = pPre->changeState();  

15.    free(pPre);  

16.    return;     

17.}  

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

命令模式的目的主要是为了把命令者和执行者分开。

老规矩,举个范例吧。

假设李老板是一家公司的头儿,他现在让他的秘书王小姐去送一封信。

王小姐当然不会自己亲自把信送到目的地,她会把信交给邮局来完成整个投递的全过程。

现在,我们就对投递者、命令、发令者分别作出定义。

  首先定义post的相关数据。

[cpp] viewplaincopy

1.typedef struct _Post  

2.{  

3.    void (*do)(struct _Post* pPost);     

4.}Post;  

  Post完成了实际的投递工作,那么命令呢?

[cpp] viewplaincopy

1.typedef struct _Command  

2.{  

3.    void* pData;  

4.    void (*exe)(struct _Command* pCommand);  

5.  

6.}Command;  

7.  

8.void post_exe(struct _Command* pCommand)  

9.{  

10.    assert(NULL !

= pCommand);  

11.   

12.    (Post*)(pCommand->pData)->do((Post*)(pCommand->pData));  

13.    return;  

14.}  

  我们看到了Post、Command的操作,那么剩下的就是boss的定义了。

[cpp] viewplaincopy

1.typedef struct _Boss  

2.{  

3.    Command* pCommand;  

4.    void (*call)(struct _Boss* pBoss);  

5.}Boss;  

6.  

7.void boss_call(struct _Boss* pBoss)  

8.{  

9.    assert(NULL !

= pBoss);  

10.  

11.    pBoss->pCommand->exe(pBoss->pCommand);  

12.    return;  

13.}  

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

 解释器模式虽然听上去有些费解,但是如果用示例说明一下就不难理解了。

我们知道在C语言中,关于变量的定义是这样的:

一个不以数字开始的由字母、数字和下划线构成的字符串。

这种形式的表达式可以用状态自动机解决,当然也可以用解释器的方式解决。

[cpp] viewplaincopy

1.typedef struct _Interpret  

2.{  

3.    int type;  

4.    void* (*process)(void* pData, int* type, int* result);  

5.  

6.}Interpret;  

  上面的数据结构比较简单,但是很能说明问题。

就拿变量来说吧,这里就可以定义成字母的解释器、数字解释器、下划线解释器三种形式。

所以,我们可以进一步定义一下process的相关函数。

[cpp] viewplaincopy

1.#define DIGITAL_TYPE 1  

2.#define LETTER_TYPE  2  

3.#define BOTTOM_LINE  3  

4.  

5.void* digital_process(void* pData, int* type, int* result)  

6.{  

7.    UINT8* str;  

8.    assert(NULL !

= pData && NULL !

= type && NULL !

= result);  

9.  

10.    str = (UNT8*)pData;  

11.    while (*str >= '0' && *str <= '9')  

12.    {  

13.        str ++;  

14.    }   

15.  

16.    if(*str == '\0')  

17.    {  

18.        *result = TRUE;  

19.        return NULL;  

20.    }     

21.  

22.    if(*str == '_')  

23.    {  

24.        *result = TRUE;  

25.        *type = BOTTOM_TYPE;  

26.        return str;  

27.    }  

28.  

29.    if(*str >= 'a' && *str <= 'z' || *str >= 'A' && *str <= 'Z')  

30.    {  

31.        *result = TRUE;  

32.        *type = LETTER_TYPE;  

33.        return str;  

34.    }  

35.  

36.    *result = FALSE;  

37.    return NULL;              

38.}      

39.  

40.void* letter_process(void* pData, int* type, int* result)  

41.{  

42.    UINT8* str;  

43.    assert(NULL !

= pData && NULL !

= type && NULL !

= result);  

44.  

45.    str = (UNT8*)pData;  

46.    while (*str >= 'a' && *str <= 'z' || *str >= 'A' && *str <= 'Z')  

47.    {  

48.        str ++;  

49.    }   

50.  

51.    if(*str == '\0')  

52.    {  

53.        *result = TRUE;  

54.        return NULL;  

55.    }     

56.  

57.    if(*str == '_')  

58.    {  

59.        *result = TRUE;  

60.        *type = BOTTOM_TYPE;  

61.        return str;  

62.    }  

63.  

64.    if(*str >= '0' && *str <= '9')  

65.    {  

66.        *result = TRUE;  

67.        *type = DIGITAL_TYPE;  

68.        return str;  

69.    }  

70.  

71.    *result = FALSE;  

72.    return NULL;              

73.}            

74.  

75.void* bottom_process(void* pData, int* type, int* result)  

76.{  

77.    UINT8* str;  

78.    assert(NULL !

= pData && NULL !

= type && NULL !

= result);  

79.  

80.    str = (UNT8*)pData;  

81.    while ('_' == *str )  

82.    {  

83.        str ++;  

84.    }   

85.  

86.    if(*str == '\0')  

87.    {  

88.        *result = TRUE;  

89.        return NULL;  

90.    }     

91.  

92.    if(*str >= 'a' && *str <= 'z' || *str >= 'A' && *str <= 'Z')  

93.    {  

94.        *result = TRUE;  

95.        *type = LETTER_TYPE;  

96.        return str;  

97.    }  

98.  

99.    if(*str >= '0' && *str <= '9')  

100.    {  

101.        *result = TRUE;  

102.        *type = DIGITAL_TYPE;  

103.        return str;  

104.    }  

105.  

106.    *result = FALSE;  

107.    return NULL;              

108.}   

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

备忘录模式的起源来自于撤销的基本操作。

有过word软件操作经验的朋友,应该基本上都使用过撤销的功能。

举个例子,假设你不小心删除了好几个段落的文字,这时候你应该怎么办呢?

其实要做的很简单,单击一些【撤销】就可以全部搞定了。

撤销按钮给我们提供了一次反悔的机会。

  既然是撤销,那么我们在进行某种动作的时候,就应该创建一个相应的撤销操作?

这个撤销操作的相关定义可以是这样的。

[cpp] viewplaincopy

1.typedef struct _Action  

2.{  

3.    int type;  

4.    struct _Action* next;  

5.  

6.    void* pData;  

7.    void (*process)(void* pData);  

8.  

9.}Action;  

  数据结构中定义了两个部分:

撤销的数据、恢复的操作。

那么这个撤销函数应该有一个创建的函数,还有一个恢复的函数。

所以,作为撤销动作的管理者应该包括,

[cpp] viewplaincopy

1.typedef struct _Organizer  

2.{  

3.    int number;  

4.    Action* pActionHead;  

5.  

6.    Action* (*create)();  

7.    void (*restore)(struct _Organizer* pOrganizer);   

8.}Organizer;  

  既然数据在创建和修改的过程中都会有相应的恢复操作,那么要是真正恢复原来的数据也就变得非常简单了。

[cpp] viewplaincopy

1.void restore(struct _Organizer* pOrganizer)  

2.{  

3.    Action* pHead;  

4.    assert(NULL !

= pOrganizer);  

5.  

6.    pHead = pOrganizer->pActionHead;  

7.    pHead->process(pHead->pData);  

8.    pOrganizer->pActionHead = pHead->next;  

9.    pOrganizer->number --;  

10.    free(pHead);  

11.    return;  

12.}  

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

观察者模式可能是我们在软件开发中使用得比较多的一种设计模式。

为什么这么说?

大家可以听我一一到来。

我们知道,在windows的软件中,所有的界都是由窗口构成的。

对话框是窗口,菜单是窗口,工具栏也是窗口。

那么这些窗口,在很多情况下要对一些共有的信息进行处理。

比如说,窗口的放大,窗口的减小等等。

面对这一情况,观察者模式就是不错的一个选择。

  首先,我们可以对这些共有的object进行提炼。

[cpp] viewplaincopy

1.typedef struct _Object  

2.{  

3.    observer* pObserverList[MAX_BINDING_NUMBER];  

4.    int number;  

5.  

6.    void (*notify)(struct _Object* pObject);  

7.    void (*add_observer)(observer* pObserver);  

8.    void (*del_observer)(observer* pObserver);  

9.  

10.}Object;  

  其实,我们需要定义的就是观察者本身了。

就像我们前面说的一样,观察者可以是菜单、工具栏或者是子窗口等等。

[cpp] viewplaincopy

1.typedef struct _Observer  

2.{  

3.    Object* pObject;  

4.  

5.    void (*update)(struct _Observer* pObserver);  

6.}Observer;   

  紧接着,我们要做的就是在Observer创建的时候,把observer自身绑定到Object上面。

[cpp] viewplaincopy

1.void bind_observer_to_object(Observer* pObserver, Object* pObject)  

2.{  

3.    assert(NULL !

= pObserver && NULL !

= pObject);  

4.  

5.    pObserver->pObject = pObject;  

6.    pObject->add_observer(pObserver);  

7.}        

8.  

9.void unbind_observer_from_object(Observer* pObserver, Object* pObject)  

10.{  

11.    assert(NULL !

= pObserver && NULL !

= pObject);  

12.  

13.    pObject->del_observer(observer* pObserver);  

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2