C语言设计模式.docx
- 文档编号:3990279
- 上传时间:2022-11-27
- 格式:DOCX
- 页数:46
- 大小:36.57KB
C语言设计模式.docx
《C语言设计模式.docx》由会员分享,可在线阅读,更多相关《C语言设计模式.docx(46页珍藏版)》请在冰豆网上搜索。
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. pObs
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 设计 模式