




已閱讀5頁,還剩21頁未讀, 繼續(xù)免費閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
目錄1.C語言設(shè)計模式(開篇)22.C語言和設(shè)計模式(繼承、封裝、多態(tài))32.1繼承性32.2封裝性42.3多態(tài)43.單件模式44.工廠模式65.抽象工廠模式76.訪問者模式97.狀態(tài)模式108.命令模式119.解釋器模式1210.備忘錄模式1311.觀察者模式1412.橋接模式1513.建造者模式1614.中介者模式1715.策略模式1816.適配器模式1917.裝飾模式2118.亨元模式2119.代理模式2320.外觀模式2421.迭代器模式2622.責(zé)任鏈模式2723模版模式2824.組合模式3025.原型模式311.C語言設(shè)計模式(開篇) 關(guān)于軟件設(shè)計方面的書很多,比如重構(gòu),比如設(shè)計模式。至于軟件開發(fā)方式,那就更多了,什么極限編程、精益方法、敏捷方法。隨著時間的推移,很多的方法又會被重新提出來。 其實,就我個人看來,不管什么方法都離不開人。一個人寫不出二叉樹,你怎么讓他寫?敏捷嗎?你寫一行,我寫一行。還是迭代?寫三行,刪掉兩行,再寫三行。項目的成功是偶然的,但是項目的失敗卻有很多原因,管理混亂、需求混亂、設(shè)計低劣、代碼質(zhì)量差、測試不到位等等。就軟件企業(yè)而言,沒有比優(yōu)秀的文化和出色的企業(yè)人才更重要的了。 從軟件設(shè)計層面來說,一般來說主要包括三個方面: (1)軟件的設(shè)計受眾,是小孩子、老人、女性,還是專業(yè)人士等等; (2)軟件的基本設(shè)計原則,以人為本、模塊分離、層次清晰、簡約至上、適用為先、抽象基本業(yè)務(wù)等等; (3)軟件編寫模式,比如裝飾模式、責(zé)任鏈、單件模式等等。 從某種意義上說,設(shè)計思想構(gòu)成了軟件的主題。軟件原則是我們在開發(fā)中的必須遵循的準(zhǔn)繩。軟件編寫模式是開發(fā)過程中的重要經(jīng)驗總結(jié)。靈活運用設(shè)計模式,一方面利于我們編寫高質(zhì)量的代碼,另一方面也方便我們對代碼進(jìn)行維護(hù)。畢竟對于廣大的軟件開發(fā)者來說,軟件的維護(hù)時間要比軟件編寫的時間要多得多。編寫過程中,難免要有新的需求,要和別的模塊打交道,要對已有的代碼進(jìn)行復(fù)用,那么這時候設(shè)計模式就派上了用場。我們討論的主題其實就是設(shè)計模式。 講到設(shè)計模式,人們首先想到的語言就是c#或者是java,最不濟(jì)也是c+,一般來說沒有人會考慮到c語言。其實,我認(rèn)為設(shè)計模式就是一種基本思想,過度美化或者神化其實沒有必要。其實閱讀過linux kernel的朋友都知道,linux雖然自身支持很多的文件系統(tǒng),但是linux自身很好地把這些系統(tǒng)的基本操作都抽象出來了,成為了基本的虛擬文件系統(tǒng)。 舉個例子來說,現(xiàn)在讓你寫一個音樂播放器,但是要支持的文件格式很多,什么ogg,wav,mp3啊,統(tǒng)統(tǒng)要支持。這時候,你會怎么編寫呢?如果用C+語言,你可能會這么寫。class music_file HANDLE hFile;public: void music_file() virtual music_file() virtual void read_file() virtual void play() virtual void stop() virtual void back() virtual void front() virtual void up() virtual void down() ; 其實,你想想看,如果用C語言能夠完成相同的抽象操作,那不是效果一樣的嗎?typedef struct _music_file HANDLE hFile; void (*read_file)(struct _music_file* pMusicFile); void (*play)(struct _music_file* pMusicFile); void (*stop)(struct _music_file* pMusicFile); void (*back)(struct _music_file* pMusicFile); void (*front)(struct _music_file* pMusicFile); void (*down)(struct _music_file* pMusicFile); void (*up)(struct _music_file* pMusicFile); music_file;當(dāng)然,上面的例子比較簡單,但是也能說明一些問題。寫這篇文章的目的一是希望和朋友們共同學(xué)習(xí)模式的相關(guān)內(nèi)容,另一方面也希望朋友們能夠活學(xué)活用,既不要迷信權(quán)威,也不要妄自菲薄。只要付出努力,付出汗水,肯定會有收獲的。有些大環(huán)境你改變不了,那就從改變自己開始。萬丈高樓平地起,一步一個腳印才能真真實實學(xué)到東西。如果盲目崇拜,言必google、微軟、apple,那么除了帶來幾個唾沫星,還能有什么受用呢?無非白費了口舌而已。 希望和大家共勉。2.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言的三個重要屬性。2.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ù)的強(qiáng)轉(zhuǎn)、數(shù)據(jù)的訪問都不會有什么問題。2.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)體擁有的屬性。2.3多態(tài)3.單件模式有過面試經(jīng)驗的朋友,或者對設(shè)計模式有點熟悉的朋友,都會對單件模式不陌生。對很多面試官而言,單件模式更是他們面試的保留項目。其實,我倒認(rèn)為,單件模式算不上什么設(shè)計模式。最多也就是個技巧。單件模式要是用C+寫,一般這么寫。#include #include class objectpublic: static class object* pObject; static object* create_new_object() if(NULL != pObject)return pObject;pObject = new object();assert(NULL != pObject);return pObject; private: object() object() ;class object* object:pObject = NULL;單件模式的技巧就在于類的構(gòu)造函數(shù)是一個私有的函數(shù)。但是類的構(gòu)造函數(shù)又是必須創(chuàng)建的?怎么辦呢?那就只有動用static函數(shù)了。我們看到static里面調(diào)用了構(gòu)造函數(shù),就是這么簡單。int main(int argc, char* argv)object* pGlobal = object:create_new_object();return 1;4.工廠模式工廠模式是比較簡單,也是比較好用的一種方式。根本上說,工廠模式的目的就根據(jù)不同的要求輸出不同的產(chǎn)品。比如說吧,有一個生產(chǎn)鞋子的工廠,它能生產(chǎn)皮鞋,也能生產(chǎn)膠鞋。如果用代碼設(shè)計,應(yīng)該怎么做呢?typedef struct _Shoe int type; void (*print_shoe)(struct _Shoe*);Shoe; 就像上面說的,現(xiàn)在有膠鞋,那也有皮鞋,我們該怎么做呢?void print_leather_shoe(struct _Shoe* pShoe) assert(NULL != pShoe); printf(This is a leather show!n);void print_rubber_shoe(struct _Shoe* pShoe) assert(NULL != pShoe); printf(This is a rubber shoe!n);所以,對于一個工廠來說,創(chuàng)建什么樣的鞋子,就看我們輸入的參數(shù)是什么?至于結(jié)果,那都是一樣的。#define LEATHER_TYPE 0x01#define RUBBER_TYPE 0x02Shoe* manufacture_new_shoe(int type) assert(LEATHER_TYPE = type | RUBBER_TYPE = type); Shoe* pShoe = (Shoe*)malloc(sizeof(Shoe); assert(NULL != pShoe); memset(pShoe, 0, sizeof(Shoe); if(LEATHER_TYPE = type) pShoe-type = LEATHER_TYPE; pShoe-print_shoe = print_leather_shoe; else pShoe-type = RUBBER_TYPE; pShoe-print_shoe = print_rubber_shoe; return pShoe;5.抽象工廠模式前面我們寫過的工廠模式實際上是對產(chǎn)品的抽象。對于不同的用戶需求,我們可以給予不同的產(chǎn)品,而且這些產(chǎn)品的接口都是一致的。而抽象工廠呢?顧名思義,就是說我們的工廠是不一定的。怎么理解呢,舉個例子。 假設(shè)有兩個水果店都在賣水果,都賣蘋果和葡萄。其中一個水果店買白蘋果和白葡萄,另外一個水果店賣紅蘋果和紅葡萄。所以說,對于水果店而言,盡管都在賣水果,但是兩個店賣的品種不一樣。 既然水果不一樣,那我們先定義水果。typedef struct _Apple void (*print_apple)();Apple;typedef struct _Grape void (*print_grape)();Grape;上面分別對蘋果和葡萄進(jìn)行了抽象,當(dāng)然它們的具體函數(shù)也是不一樣的。void print_white_apple() printf(white apple!n);void print_red_apple() printf(red apple!n);void print_white_grape() printf(white grape!n);void print_red_grape() printf(red grape!n);完成了水果函數(shù)的定義。下面就該定義工廠了,和水果一樣,我們也需要對工廠進(jìn)行抽象處理。typedef struct _FruitShop Apple* (*sell_apple)(); Grape * (*sell_grape)();FruitShop; 所以,對于賣白蘋果、白葡萄的水果店就該這樣設(shè)計了,紅蘋果、紅葡萄的水果店亦是如此。Apple* sell_white_apple() Apple* pApple = (Apple*) malloc(sizeof(Apple); assert(NULL != pApple); pApple-print_apple = print_white_apple; return pApple;Grape* sell_white_grape() Grape* pGrape = (Grape*) malloc(sizeof(Grape); assert(NULL != pGrape); pGrape-print_grape = print_white_grape; return pGrape;這樣,基本的框架就算搭建完成的,以后創(chuàng)建工廠的時候,F(xiàn)ruitShop* create_fruit_shop(int color) FruitShop* pFruitShop = (FruitShop*) malloc(sizeof(FruitShop); assert(NULL != pFruitShop); if(WHITE = color) pFruitShop-sell_apple = sell_white_apple; pFruitShop-sell_grape = sell_white_grape; else pFruitShop-sell_apple = sell_red_apple; pFruitShop-sell_grape = sell_red_grape; return pFruitShop;6.訪問者模式不知不覺當(dāng)中,我們就到了最后一種設(shè)計模式,即訪問者模式。訪問者模式,聽上去復(fù)雜一些。但是,這種模式用簡單的一句話說,就是不同的人對不同的事物有不同的感覺。比如說吧,豆腐可以做成麻辣豆腐,也可以做成臭豆腐??墒?,不同的地方的人未必都喜歡這兩種豆腐。四川的朋友可能更喜歡辣豆腐,江浙的人就可能對臭豆腐更喜歡一些。那么,這種情況應(yīng)該怎么用設(shè)計模式表達(dá)呢?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;7.狀態(tài)模式 狀態(tài)模式是協(xié)議交互中使用得比較多的模式。比如說,在不同的協(xié)議中,都會存在啟動、保持、中止等基本狀態(tài)。那么怎么靈活地轉(zhuǎn)變這些狀態(tài)就是我們需要考慮的事情。假設(shè)現(xiàn)在有一個state, 說明一下,這里定義了兩個變量,分別process函數(shù)和change_state函數(shù)。其中proces函數(shù)就是普通的數(shù)據(jù)操作,void normal_process() printf(normal process!n); change_state函數(shù)本質(zhì)上就是確定下一個狀態(tài)是什么。所以,在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; 8.命令模式 命令模式的目的主要是為了把命令者和執(zhí)行者分開。老規(guī)矩,舉個范例吧。假設(shè)李老板是一家公司的頭兒,他現(xiàn)在讓他的秘書王小姐去送一封信。王小姐當(dāng)然不會自己親自把信送到目的地,她會把信交給郵局來完成整個投遞的全過程?,F(xiàn)在,我們就對投遞者、命令、發(fā)令者分別作出定義。首先定義post的相關(guān)數(shù)據(jù)。typedef struct _Post void (*do)(struct _Post* pPost); Post;Post完成了實際的投遞工作,那么命令呢?void post_exe(struct _Command* pCommand) assert(NULL != pCommand); (Post*)(pCommand-pData)-do(Post*)(pCommand-pData); return;我們看到了Post、Command的操作,那么剩下的就是boss的定義了。typedef struct _Boss Command* pCommand; void (*call)(struct _Boss* pBoss);Boss;void boss_call(struct _Boss* pBoss) assert(NULL != pBoss); pBoss-pCommand-exe(pBoss-pCommand); return;9.解釋器模式 命令模式的目的主要是為了把命令者和執(zhí)行者分開。老規(guī)矩,舉個范例吧。假設(shè)李老板是一家公司的頭兒,他現(xiàn)在讓他的秘書王小姐去送一封信。王小姐當(dāng)然不會自己親自把信送到目的地,她會把信交給郵局來完成整個投遞的全過程?,F(xiàn)在,我們就對投遞者、命令、發(fā)令者分別作出定義。首先定義post的相關(guān)數(shù)據(jù)。typedef struct _Post void (*do)(struct _Post* pPost); Post;Post完成了實際的投遞工作,那么命令呢?void post_exe(struct _Command* pCommand) assert(NULL != pCommand); (Post*)(pCommand-pData)-do(Post*)(pCommand-pData); return;我們看到了Post、Command的操作,那么剩下的就是boss的定義了。typedef struct _Boss Command* pCommand; void (*call)(struct _Boss* pBoss);Boss;void boss_call(struct _Boss* pBoss) assert(NULL != pBoss); pBoss-pCommand-exe(pBoss-pCommand); return;10.備忘錄模式 備忘錄模式的起源來自于撤銷的基本操作。有過word軟件操作經(jīng)驗的朋友,應(yīng)該基本上都使用過撤銷的功能。舉個例子,假設(shè)你不小心刪除了好幾個段落的文字,這時候你應(yīng)該怎么辦呢?其實要做的很簡單,單擊一些【撤銷】就可以全部搞定了。撤銷按鈕給我們提供了一次反悔的機(jī)會。既然是撤銷,那么我們在進(jìn)行某種動作的時候,就應(yīng)該創(chuàng)建一個相應(yīng)的撤銷操作?這個撤銷操作的相關(guān)定義可以是這樣的。typedef struct _Action int type; struct _Action* next; void* pData; void (*process)(void* pData);Action;數(shù)據(jù)結(jié)構(gòu)中定義了兩個部分:撤銷的數(shù)據(jù)、恢復(fù)的操作。那么這個撤銷函數(shù)應(yīng)該有一個創(chuàng)建的函數(shù),還有一個恢復(fù)的函數(shù)。所以,作為撤銷動作的管理者應(yīng)該包括,既然數(shù)據(jù)在創(chuàng)建和修改的過程中都會有相應(yīng)的恢復(fù)操作,那么要是真正恢復(fù)原來的數(shù)據(jù)也就變得非常簡單了。void restore(struct _Organizer* pOrganizer) Action* pHead; assert(NULL != pOrganizer); pHead = pOrganizer-pActionHead; pHead-process(pHead-pData); pOrganizer-pActionHead = pHead-next; pOrganizer-number -; free(pHead); return;11.觀察者模式 觀察者模式可能是我們在軟件開發(fā)中使用得比較多的一種設(shè)計模式。為什么這么說?大家可以聽我一一到來。我們知道,在windows的軟件中,所有的界都是由窗口構(gòu)成的。對話框是窗口,菜單是窗口,工具欄也是窗口。那么這些窗口,在很多情況下要對一些共有的信息進(jìn)行處理。比如說,窗口的放大,窗口的減小等等。面對這一情況,觀察者模式就是不錯的一個選擇。首先,我們可以對這些共有的object進(jìn)行提煉。既然Observer在創(chuàng)建的時候就把自己綁定在某一個具體的Object上面,那么Object發(fā)生改變的時候,統(tǒng)一更新操作就是一件很容易的事情了。void notify(struct _Object* pObject) Obserer* pObserver; int index; assert(NULL != pObject); for(index = 0; index number; index+) pObserver = pObjecet-pObserverListindex; pObserver-update(pObserver); 12.橋接模式 在以往的軟件開發(fā)過程中,我們總是強(qiáng)調(diào)模塊之間要低耦合,模塊本身要高內(nèi)聚。那么,可以通過哪些設(shè)計模式來實現(xiàn)呢?橋接模式就是不錯的一個選擇。我們知道,在現(xiàn)實的軟件開發(fā)過程當(dāng)中,用戶的要求是多種多樣的。比如說,有這么一個餃子店吧。假設(shè)餃子店原來只賣肉餡的餃子,可是后來一些吃素的顧客說能不能做一些素的餃子。聽到這些要求的老板自然不敢怠慢,所以也開始賣素餃子。之后,又有顧客提出,現(xiàn)在的肉餡餃子只有豬肉的,能不能做點牛肉、羊肉餡的餃子?一些只吃素的顧客也有意見了,他們建議能不能增加一些素餡餃子的品種,什么白菜餡的、韭菜餡的,都可以做一點。由此看來,顧客的要求是一層一層遞增的。關(guān)鍵是我們?nèi)绾伟杨櫩偷囊蠛臀覀兊膶崿F(xiàn)的接口進(jìn)行有效地分離呢?上面只是對餃子進(jìn)行歸類。第一類是對肉餡餃子的歸類,第二類是對素餡餃子的歸類,這些地方都沒有什么特別之處。那么,關(guān)鍵是我們怎么把它和顧客的要求聯(lián)系在一起呢?typedef struct _DumplingReuqest int type; void* pDumpling; DumplingRequest;這里定義了一個餃子買賣的接口。它的特別支持就在于兩個地方,第一是我們定義了餃子的類型type,這個type是可以隨便擴(kuò)充的;第二就是這里的pDumpling是一個void*指針,只有把它和具體的dumpling綁定才會衍生出具體的含義。void buy_dumpling(DumplingReuqest* pDumplingRequest) assert(NULL != pDumplingRequest); if(MEAT_TYPE = pDumplingRequest-type) return (MeatDumpling*)(pDumplingRequest-pDumpling)-make(); else return (NormalDumpling*)(pDumplingRequest-pDumpling)-make();13.建造者模式 如果說前面的工廠模式是對接口進(jìn)行抽象化處理,那么建造者模式更像是對流程本身的一種抽象化處理。這話怎么理解呢?大家可以聽我慢慢到來。以前買電腦的時候,大家都喜歡自己組裝機(jī)器。一方面可以滿足自己的個性化需求,另外一方面也可以在價格上得到很多實惠。但是電腦是由很多部分組成的,每個廠家都只負(fù)責(zé)其中的一部分,而且相同的組件也有很多的品牌可以從中選擇。這對于我們消費者來說當(dāng)然非常有利,那么應(yīng)該怎么設(shè)計呢? typedef struct _AssemblePersonalComputer void (*assemble_cpu)(); void (*assemble_memory)(); void (*assemble_harddisk)();AssemblePersonalComputer;對于一個希望配置intel cpu,samsung 內(nèi)存、日立硬盤的朋友。他可以這么設(shè)計,14.中介者模式 中介者模式,聽上去有一點陌生。但是,只要我給朋友們打個比方就明白了。早先自由戀愛沒有現(xiàn)在那么普遍的時候,男女之間的相識還是需要通過媒婆之間才能相互認(rèn)識。男孩對女方有什么要求,可以通過媒婆向女方提出來;當(dāng)然,女方有什么要求也可以通過媒婆向男方提出來。所以,中介者模式在我看來,就是媒婆模式。 typedef struct _Mediator People* man; People* woman; Mediator;上面的數(shù)據(jù)結(jié)構(gòu)是給媒婆的,那么當(dāng)然還有一個數(shù)據(jù)結(jié)構(gòu)是給男方、女方的。typedef struct _People Mediator* pMediator; void (*request)(struct _People* pPeople); void (*process)(struct _Peoplle* pPeople);People;所以,這里我們看到的如果是男方的要求,那么這個要求應(yīng)該女方去處理啊,怎么處理呢?void man_request(struct _People* pPeople) assert(NULL != pPeople); pPeople-pMediator-woman-process(pPeople-pMediator-woman); 上面做的是男方向女方提出的要求,所以女方也可以向男方提要求了。畢竟男女平等嘛。void woman_request(struct _People* pPeople) assert(NULL != pPeople); pPeople-pMediator-man-process(pPeople-pMediator-man);15.策略模式 策略模式就是用統(tǒng)一的方法接口分別對不同類型的數(shù)據(jù)進(jìn)行訪問。比如說,現(xiàn)在我們想用pc看一部電影,此時應(yīng)該怎么做呢?看電影嘛,當(dāng)然需要各種播放電影的方法。rmvb要rmvb格式的方法,avi要avi的方法,mpeg要mpeg的方法。可是事實上,我們完全可以不去管是什么文件格式。因為播放器對所有的操作進(jìn)行了抽象,不同的文件會自動調(diào)用相應(yīng)的訪問方法。 typedef struct _MoviePlay struct _CommMoviePlay* pCommMoviePlay;MoviePlay;這個時候呢,對于用戶來說,統(tǒng)一的文件接口就是MoviePlay。接下來的一個工作,就是編寫一個統(tǒng)一的訪問接口。void play_movie_file(struct MoviePlay* pMoviePlay) CommMoviePlay* pCommMoviePlay; assert(NULL != pMoviePlay); pCommMoviePlay = pMoviePlay-pCommMoviePlay; pCommMoviePlay-play(pCommMoviePlay-hFile); 最后的工作就是對不同的hFile進(jìn)行play的實際操作,寫簡單一點就是,void play_avi_file(HANDLE hFile) printf(play avi file!n);void play_rmvb_file(HANDLE hFile) printf(play rmvb file!n);void play_mpeg_file(HANDLE hFile) printf(play mpeg file!n);16.適配器模式 現(xiàn)在的生活當(dāng)中,我們離不開各種電子工具。什么筆記本電腦、手機(jī)、mp4啊,都離不開充電。既然是充電,那么就需要用到充電器。其實從根本上來說,充電器就是一個個普通的適配器。什么叫適配器呢,就是把220v、50hz的交流電壓編程512v的直流電壓。充電器就干了這么一件事情。那么,這樣的一個充電適配器,我們應(yīng)該怎么用c+描述呢?class voltage_12vpublic: voltage_12v() virtual voltage_12v() virtual void request() ;class adapter: public voltage_12v v220_to_v12* pAdaptee;public: adapter() adapter() void request() pAdaptee-voltage_transform_process(); ;通過上面的代碼,我們其實可以這樣理解。類voltage_12v表示我們的最終目的就是為了獲得一個12v的直流電壓。當(dāng)然獲得12v可以有很多的方法,利用適配器轉(zhuǎn)換僅僅是其中的一個方法。adapter表示適配器,它自己不能實現(xiàn)220v到12v的轉(zhuǎn)換工作,所以需要調(diào)用類v220_to_v12的轉(zhuǎn)換函數(shù)。所以,我們利用adapter獲得12v的過程,其實就是調(diào)用v220_to_v12函數(shù)的過程。 不過,既然我們的主題是用c語言來編寫適配器模式,那么我們就要實現(xiàn)最初的目標(biāo)。這其實也不難,關(guān)鍵一步就是定義一個Adapter的數(shù)據(jù)結(jié)構(gòu)。然后把所有的Adapter工作都由Adaptee來做,就是這么簡單。不知我說明白了沒有?typdef struct _Adaptee void (*real_process)(struct _Adaptee* pAdaptee);Adaptee;17.裝飾模式 裝飾模式是比較好玩,也比較有意義。其實就我個人看來,它和責(zé)任鏈還是蠻像的。只不過一個是比較判斷,一個是迭代處理。裝飾模式就是那種迭代處理的模式,關(guān)鍵在哪呢?我們可以看看數(shù)據(jù)結(jié)構(gòu)。 typedef struct _Object struct _Object* prev; void (*decorate)(struct _Object* pObject);Object;裝飾模式最經(jīng)典的地方就是把pObject這個值放在了數(shù)據(jù)結(jié)構(gòu)里面。當(dāng)然,裝飾模式的奧妙還不僅僅在這個地方,還有一個地方就是迭代處理。我們可以自己隨便寫一個decorate函數(shù)試試看,void decorate(struct _Object* pObeject) assert(NULL != pObject); if(NULL != pObject-prev) pObject-prev-decorate(pObject-prev); printf(normal decorate!n);所以,裝飾模式的最重要的兩個方面就體現(xiàn)在:prev參數(shù)和decorate迭代處理。18.亨元模式享元模式看上去有點玄乎,但是其實也沒有那么復(fù)雜。我們還是用示例說話。比如說,大家在使用電腦的使用應(yīng)該少不了使用WORD軟件。使用WORD呢, 那就少不了設(shè)置模板。什么模板呢,比如說標(biāo)題的模板,正文的模板等等。這些模板呢,又包括很多的內(nèi)容。哪些方面呢,比如說字體、標(biāo)號、字距、行距、大小等等。 上面的Font表示了各種Font的模板形式。所以,下面的方法就是定制一個FontFactory的結(jié)構(gòu)。typedef struct _FontFactory Font* ppFont; int number; int size; Font* GetFont(struct _FontFactory* pFontFactory, int type, int sequence, int gap, int lineDistance);FontFactory;這里的GetFont即使對當(dāng)前的Font進(jìn)行判斷,如果Font存在,那么返回;否則創(chuàng)建一個新的Font模式。Font* GetFont(struct _FontFactory* pFontFactory, int type, int sequence, int gap, int lineDistance) int index; Font* pFont; Font* ppFont; if(NULL = pFontFactory) return NULL; for(index = 0; index number; index+) if(type != pFontFactory-ppFontindex-type) continue; if(sequence != pFontFactory-ppFontindex-sequence) continue; if(gap != pFontFactory-ppFontindex-gap) continue; if(lineDistance != pFontFactory-ppFontindex-lineDistance) continue; return pFontFactory-ppFontindex; pFont = (Font*)malloc(sizeof(Font);19.代理模式 代理模式是一種比較有意思的設(shè)計模式。它的基本思路也不復(fù)雜。舉個例子來說,以前在學(xué)校上網(wǎng)的時候,并不是每一臺pc都有上網(wǎng)的權(quán)限的。比如說,現(xiàn)在有pc1、pc2、pc3,但是只有pc1有上網(wǎng)權(quán)限,但是pc2、pc3也想上網(wǎng),此時應(yīng)該怎么辦呢? 此時,我們需要做的就是在pc1上開啟代理軟件,同時把pc2、pc3的IE代理指向pc1即可。這個時候,如果pc2或者pc3想上網(wǎng),那么報文會先指向pc1,然后pc1把Internet傳回的報文再發(fā)給pc2或者pc3。這樣一個代理的過程就完成了整個的上網(wǎng)過程。在說明完整的過程之后,我們可以考慮一下軟件應(yīng)該怎么編寫呢?void ftp_request() printf(request from ftp!n);void http_request() printf(request from http!n);void smtp_request() printf(request from smtp!n); 這個時候,代理的操作應(yīng)該怎么寫呢?怎么處理來自各個協(xié)議的請求呢?typedef struct _Proxy PC_Client* pClient;Proxy;void process(Proxy* pProxy) assert(NULL != pProxy); pProxy-pClient-request();20.外觀模式 外觀模式是比較簡單的模式。它的目的也是為了簡單。什么意思呢?舉個例子吧。以前,我們逛街的時候吃要到小吃一條街,購物要到購物一條街,看書、看電影要到文化一條街。那么有沒有這樣的地方,既可以吃喝玩樂,同時相互又靠得比較近呢。其實,這就是悠閑廣場,遍布全國的萬達(dá)廣場就是干了這么一件事。首先,我們原來是怎么做的。typedef struct _ShopStreet void (*buy)();ShopStreet;void buy() printf(buy here!n);typedef struct _BookStreet void (*read)();BookStreet;void read() printf(read here); 下面,我們就要在一個plaza里面完成所有的項目,怎么辦呢?typedef struct _Plaza FoodStreet* pFoodStreet; ShopStreet* pShopStreet; BookStreet* pBookStreet; void (*play)(struct _Plaza* pPlaza); Plaza;void play(struct _Plaza* pPlaza) assert(NULL != pPlaza); pPlaza-pFoodStreet-eat(); pPlaza-pShopStreet-buy(); pPlaza-pBookStreet-read();21.迭代器模式 使用過C+的朋友大概對迭代器模式都不會太陌生。這主要是因為我們在編寫代碼的時候離不開迭代器,隊列有迭代器,向量也有迭代器。那么,為什么要迭代器呢?這主要是為了提煉一種通用的數(shù)據(jù)訪問方法。比如說,現(xiàn)在有一個數(shù)據(jù)的容器,我們看到,容器有g(shù)et_first,迭代器也有g(shù)et_first,這中間有什么區(qū)別?int vector_get_first(struct _Container* pContainer) assert(NULL != pContainer); return pContainer-pData0;int vector_get_last(struct _Container* pContainer) assert(NULL != pContainer); return pContainer-pDatapContainer-size -1;int vector_interator_get_first(struct _Interator* pInterator) Container* pContainer; assert(NULL != pInterator & NULL !
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025-2030年中國數(shù)顯量具產(chǎn)銷需求分析及投資發(fā)展前景預(yù)測研究報告
- 湖北省襄陽三中2025年高考英語二模試卷含解析
- 職業(yè)技術(shù)學(xué)院2024級計算機(jī)網(wǎng)絡(luò)技術(shù)專業(yè)人才培養(yǎng)方案
- 廣東省廣州市2025屆高三下學(xué)期綜合測試(二)(二模)數(shù)學(xué)試題 含解析
- 上海市金山區(qū)2024-2025學(xué)年八年級下學(xué)期中化學(xué)試題(原卷版+解析版)
- 生態(tài)環(huán)境監(jiān)測中的遙感與GIS技術(shù)考核試卷
- 電氣安裝石油與開采設(shè)備考核試卷
- 管道配件生產(chǎn)的自動化技術(shù)考核試卷
- 船舶改裝施工過程中的質(zhì)量安全管理協(xié)同考核試卷
- 納米材料在海水淡化處理中的應(yīng)用考核試卷
- 【9數(shù)一?!?025年安徽合肥市第四十五中學(xué)九年級中考一模數(shù)學(xué)試卷(含答案)
- 電網(wǎng)工程設(shè)備材料信息參考價(2024年第四季度)
- 2024年浙江省中考社會試卷真題(含標(biāo)準(zhǔn)答案及評分標(biāo)準(zhǔn))
- 國開2024年秋《生產(chǎn)與運作管理》形成性考核1-4答案
- DB43∕T 497-2009 博落回果-行業(yè)標(biāo)準(zhǔn)
- 創(chuàng)意綜藝風(fēng)脫口秀活動策劃PPT模板
- 大客戶營銷技巧ppt課件
- C++優(yōu)秀課件PPT
- 團(tuán)險新產(chǎn)品契約及核保細(xì)則
- 定向鉆(拉管)施工方案
- 柴油發(fā)電機(jī)安裝單元評定表
評論
0/150
提交評論