本文引用自本人公眾號文章:
嵌入式開發(fā)中的兩點編程思想
C語言也很講究設(shè)計模式?一文講透
包含如下:
01)C語言和設(shè)計模式(繼承、封裝、多態(tài))
02)C語言和設(shè)計模式(訪問者模式)
03)C語言和設(shè)計模式(狀態(tài)模式)
04)C語言和設(shè)計模式(命令模式)
05)C語言和設(shè)計模式(解釋器模式)
06)C語言和設(shè)計模式(備忘錄模式)
07)C語言和設(shè)計模式(觀察者模式)
08)C語言和設(shè)計模式(橋接模式)
09)C語言和設(shè)計模式(建造者模式)
10)C語言和設(shè)計模式(中介者模式)
11)C語言和設(shè)計模式(策略模式)
12)C語言和設(shè)計模式(適配器模式)
13)C語言和設(shè)計模式(裝飾模式)
14)C語言和設(shè)計模式(享元模式)
15)C語言和設(shè)計模式(代理模式)
16)C語言和設(shè)計模式(外觀模式)
17)C語言和設(shè)計模式(迭代器模式)
18)C語言和設(shè)計模式(抽象工廠模式)
19)C語言和設(shè)計模式(責(zé)任鏈模式)
20)C語言和設(shè)計模式(工廠模式)
21)C語言和設(shè)計模式(模板模式)
22)C語言和設(shè)計模式(組合模式)
23)C語言和設(shè)計模式(原型模式)
24)C語言和設(shè)計模式(單件模式)
25)C語言和設(shè)計模式(開篇)
-----------------------
01)C語言和設(shè)計模式(繼承、封裝、多態(tài))
記得還在我們大學(xué)
C++第一門課的時候,老師就告訴我們說,C++是一門面向?qū)ο蟮恼Z言。C++有三個最重要的特點,即繼承、封裝、多態(tài)。等到后來隨著編碼的增多和工作經(jīng)驗的積累,我也慢慢明白了面向?qū)ο蟮暮x。可是,等我工作以后,使用的編程語言更多的是C語言,這時候我又想能不能把C語言變成面向?qū)ο蟮恼Z言呢?等到后來通過思考和實踐,我發(fā)現(xiàn)其實C語言也是可以面向?qū)ο蟮模彩强梢詰?yīng)用設(shè)計模式的,關(guān)鍵就在于如何實現(xiàn)面向?qū)ο笳Z言的三個重要屬性。
(1)繼承性
typedef struct _parent
{
int data_parent;
}Parent;
typedef struct _Child
{
struct _parent parent;
int data_child;
}Child;
在設(shè)計C語言繼承性的時候,我們需要做的就是把基礎(chǔ)數(shù)據(jù)放在繼承的結(jié)構(gòu)的首位置即可。這樣,不管是數(shù)據(jù)的訪問、數(shù)據(jù)的強轉(zhuǎn)、數(shù)據(jù)的訪問都不會有什么問題。
(2)封裝性
struct _Data;
typedef void (*process)(struct _Data* pData);
typedef struct _Data
{
int value;
process pProcess;
}Data;
封裝性的意義在于,函數(shù)和數(shù)據(jù)是綁在一起的,數(shù)據(jù)和數(shù)據(jù)是綁在一起的。這樣,我們就可以通過簡單的一個結(jié)構(gòu)指針訪問到所有的數(shù)據(jù),遍歷所有的函數(shù)。封裝性,這是類擁有的屬性,當(dāng)然也是數(shù)據(jù)結(jié)構(gòu)體擁有的屬性。
(3)多態(tài)
typedef struct _Play
{
void* pData;
void (*start_play)(struct _Play* pPlay);
}Play;
多態(tài),就是說用同一的
接口代碼處理不同的數(shù)據(jù)。比如說,這里的Play結(jié)構(gòu)就是一個通用的數(shù)據(jù)結(jié)構(gòu),我們也不清楚pData是什么數(shù)據(jù),start_play是什么處理函數(shù)?但是,我們處理的時候只要調(diào)用pPlay->start_play(pPlay)就可以了。剩下來的事情我們不需要管,因為不同的接口會有不同的函數(shù)去處理,我們只要學(xué)會調(diào)用就可以了。
-----------------------
02)C語言和設(shè)計模式(訪問者模式)
不知不覺當(dāng)中,我們就到了最后一種設(shè)計模式,即訪問者模式。訪問者模式,聽上去復(fù)雜一些。但是,這種模式用簡單的一句話說,就是不同的人對不同的事物有不同的感覺。比如說吧,豆腐可以做成麻辣豆腐,也可以做成臭豆腐。可是,不同的地方的人未必都喜歡這兩種豆腐。四川的朋友可能更喜歡辣豆腐,江浙的人就可能對臭豆腐更喜歡一些。那么,這種情況應(yīng)該怎么用設(shè)計模式表達呢?
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函數(shù)了。
void process(struct _Tofu* pTofu, struct _Visitor* pVisitor)
{
assert(NULL != pTofu && NULL != pVisitor);
if(pTofu->type == SP
ICY_FOOD && pVisitor->region == WEST ||
pTofu->type == STRONG_SMELL_FOOD && pVisitor->region == EAST)
{
printf("I like this food!\n");
return;
}
printf("I ha
te this food!\n");
}
-----------------------------------------------------
03)C語言和設(shè)計模式(狀態(tài)模式)
狀態(tài)模式是協(xié)議交互中使用得比較多的模式。比如說,在不同的協(xié)議中,都會存在啟動、保持、中止等基本狀態(tài)。那么怎么靈活地轉(zhuǎn)變這些狀態(tài)就是我們需要考慮的事情。假設(shè)現(xiàn)在有一個state,
typedef struct _State
{
void (*process)();
struct _State* (*change_state)();
}State;
說明一下,這里定義了兩個變量,分別process函數(shù)和change_state函數(shù)。其中proces函數(shù)就是普通的數(shù)據(jù)操作,
void normal_process()
{
printf("normal process!\n");
}
change_state函數(shù)本質(zhì)上就是確定下一個狀態(tài)是什么。
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中,應(yīng)該有一個state變量,還應(yīng)該有一個state變換函數(shù)。
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;
}
評論