




已閱讀5頁(yè),還剩21頁(yè)未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
目錄1.C語(yǔ)言設(shè)計(jì)模式(開(kāi)篇)22.C語(yǔ)言和設(shè)計(jì)模式(繼承、封裝、多態(tài))32.1繼承性32.2封裝性42.3多態(tài)43.單件模式44.工廠模式65.抽象工廠模式76.訪問(wèn)者模式97.狀態(tài)模式108.命令模式119.解釋器模式1210.備忘錄模式1311.觀察者模式1412.橋接模式1513.建造者模式1614.中介者模式1715.策略模式1816.適配器模式1917.裝飾模式2118.亨元模式2119.代理模式2320.外觀模式2421.迭代器模式2622.責(zé)任鏈模式2723模版模式2824.組合模式3025.原型模式311.C語(yǔ)言設(shè)計(jì)模式(開(kāi)篇) 關(guān)于軟件設(shè)計(jì)方面的書很多,比如重構(gòu),比如設(shè)計(jì)模式。至于軟件開(kāi)發(fā)方式,那就更多了,什么極限編程、精益方法、敏捷方法。隨著時(shí)間的推移,很多的方法又會(huì)被重新提出來(lái)。 其實(shí),就我個(gè)人看來(lái),不管什么方法都離不開(kāi)人。一個(gè)人寫不出二叉樹(shù),你怎么讓他寫?敏捷嗎?你寫一行,我寫一行。還是迭代?寫三行,刪掉兩行,再寫三行。項(xiàng)目的成功是偶然的,但是項(xiàng)目的失敗卻有很多原因,管理混亂、需求混亂、設(shè)計(jì)低劣、代碼質(zhì)量差、測(cè)試不到位等等。就軟件企業(yè)而言,沒(méi)有比優(yōu)秀的文化和出色的企業(yè)人才更重要的了。 從軟件設(shè)計(jì)層面來(lái)說(shuō),一般來(lái)說(shuō)主要包括三個(gè)方面: (1)軟件的設(shè)計(jì)受眾,是小孩子、老人、女性,還是專業(yè)人士等等; (2)軟件的基本設(shè)計(jì)原則,以人為本、模塊分離、層次清晰、簡(jiǎn)約至上、適用為先、抽象基本業(yè)務(wù)等等; (3)軟件編寫模式,比如裝飾模式、責(zé)任鏈、單件模式等等。 從某種意義上說(shuō),設(shè)計(jì)思想構(gòu)成了軟件的主題。軟件原則是我們?cè)陂_(kāi)發(fā)中的必須遵循的準(zhǔn)繩。軟件編寫模式是開(kāi)發(fā)過(guò)程中的重要經(jīng)驗(yàn)總結(jié)。靈活運(yùn)用設(shè)計(jì)模式,一方面利于我們編寫高質(zhì)量的代碼,另一方面也方便我們對(duì)代碼進(jìn)行維護(hù)。畢竟對(duì)于廣大的軟件開(kāi)發(fā)者來(lái)說(shuō),軟件的維護(hù)時(shí)間要比軟件編寫的時(shí)間要多得多。編寫過(guò)程中,難免要有新的需求,要和別的模塊打交道,要對(duì)已有的代碼進(jìn)行復(fù)用,那么這時(shí)候設(shè)計(jì)模式就派上了用場(chǎng)。我們討論的主題其實(shí)就是設(shè)計(jì)模式。 講到設(shè)計(jì)模式,人們首先想到的語(yǔ)言就是c#或者是java,最不濟(jì)也是c+,一般來(lái)說(shuō)沒(méi)有人會(huì)考慮到c語(yǔ)言。其實(shí),我認(rèn)為設(shè)計(jì)模式就是一種基本思想,過(guò)度美化或者神化其實(shí)沒(méi)有必要。其實(shí)閱讀過(guò)linux kernel的朋友都知道,linux雖然自身支持很多的文件系統(tǒng),但是linux自身很好地把這些系統(tǒng)的基本操作都抽象出來(lái)了,成為了基本的虛擬文件系統(tǒng)。 舉個(gè)例子來(lái)說(shuō),現(xiàn)在讓你寫一個(gè)音樂(lè)播放器,但是要支持的文件格式很多,什么ogg,wav,mp3啊,統(tǒng)統(tǒng)要支持。這時(shí)候,你會(huì)怎么編寫呢?如果用C+語(yǔ)言,你可能會(huì)這么寫。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() ; 其實(shí),你想想看,如果用C語(yǔ)言能夠完成相同的抽象操作,那不是效果一樣的嗎?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)然,上面的例子比較簡(jiǎn)單,但是也能說(shuō)明一些問(wèn)題。寫這篇文章的目的一是希望和朋友們共同學(xué)習(xí)模式的相關(guān)內(nèi)容,另一方面也希望朋友們能夠活學(xué)活用,既不要迷信權(quán)威,也不要妄自菲薄。只要付出努力,付出汗水,肯定會(huì)有收獲的。有些大環(huán)境你改變不了,那就從改變自己開(kāi)始。萬(wàn)丈高樓平地起,一步一個(gè)腳印才能真真實(shí)實(shí)學(xué)到東西。如果盲目崇拜,言必google、微軟、apple,那么除了帶來(lái)幾個(gè)唾沫星,還能有什么受用呢?無(wú)非白費(fèi)了口舌而已。 希望和大家共勉。2.C語(yǔ)言和設(shè)計(jì)模式(繼承、封裝、多態(tài))記得還在我們大學(xué)C+第一門課的時(shí)候,老師就告訴我們說(shuō),C+是一門面向?qū)ο蟮恼Z(yǔ)言。C+有三個(gè)最重要的特點(diǎn),即繼承、封裝、多態(tài)。等到后來(lái)隨著編碼的增多和工作經(jīng)驗(yàn)的積累,我也慢慢明白了面向?qū)ο蟮暮x??墒?,等我工作以后,使用的編程語(yǔ)言更多的是C語(yǔ)言,這時(shí)候我又想能不能把C語(yǔ)言變成面向?qū)ο蟮恼Z(yǔ)言呢?等到后來(lái)通過(guò)思考和實(shí)踐,我發(fā)現(xiàn)其實(shí)C語(yǔ)言也是可以面向?qū)ο蟮模彩强梢詰?yīng)用設(shè)計(jì)模式的,關(guān)鍵就在于如何實(shí)現(xiàn)面向?qū)ο笳Z(yǔ)言的三個(gè)重要屬性。2.1繼承性typedef struct _parent int data_parent;Parent;typedef struct _Child struct _parent parent; int data_child;Child;在設(shè)計(jì)C語(yǔ)言繼承性的時(shí)候,我們需要做的就是把基礎(chǔ)數(shù)據(jù)放在繼承的結(jié)構(gòu)的首位置即可。這樣,不管是數(shù)據(jù)的訪問(wèn)、數(shù)據(jù)的強(qiáng)轉(zhuǎn)、數(shù)據(jù)的訪問(wèn)都不會(huì)有什么問(wèn)題。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ù)是綁在一起的。這樣,我們就可以通過(guò)簡(jiǎn)單的一個(gè)結(jié)構(gòu)指針訪問(wèn)到所有的數(shù)據(jù),遍歷所有的函數(shù)。封裝性,這是類擁有的屬性,當(dāng)然也是數(shù)據(jù)結(jié)構(gòu)體擁有的屬性。2.3多態(tài)3.單件模式有過(guò)面試經(jīng)驗(yàn)的朋友,或者對(duì)設(shè)計(jì)模式有點(diǎn)熟悉的朋友,都會(huì)對(duì)單件模式不陌生。對(duì)很多面試官而言,單件模式更是他們面試的保留項(xiàng)目。其實(shí),我倒認(rèn)為,單件模式算不上什么設(shè)計(jì)模式。最多也就是個(gè)技巧。單件模式要是用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ù)是一個(gè)私有的函數(shù)。但是類的構(gòu)造函數(shù)又是必須創(chuàng)建的?怎么辦呢?那就只有動(dòng)用static函數(shù)了。我們看到static里面調(diào)用了構(gòu)造函數(shù),就是這么簡(jiǎn)單。int main(int argc, char* argv)object* pGlobal = object:create_new_object();return 1;4.工廠模式工廠模式是比較簡(jiǎn)單,也是比較好用的一種方式。根本上說(shuō),工廠模式的目的就根據(jù)不同的要求輸出不同的產(chǎn)品。比如說(shuō)吧,有一個(gè)生產(chǎn)鞋子的工廠,它能生產(chǎn)皮鞋,也能生產(chǎn)膠鞋。如果用代碼設(shè)計(jì),應(yīng)該怎么做呢?typedef struct _Shoe int type; void (*print_shoe)(struct _Shoe*);Shoe; 就像上面說(shuō)的,現(xiàn)在有膠鞋,那也有皮鞋,我們?cè)撛趺醋瞿??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);所以,對(duì)于一個(gè)工廠來(lái)說(shuō),創(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.抽象工廠模式前面我們寫過(guò)的工廠模式實(shí)際上是對(duì)產(chǎn)品的抽象。對(duì)于不同的用戶需求,我們可以給予不同的產(chǎn)品,而且這些產(chǎn)品的接口都是一致的。而抽象工廠呢?顧名思義,就是說(shuō)我們的工廠是不一定的。怎么理解呢,舉個(gè)例子。 假設(shè)有兩個(gè)水果店都在賣水果,都賣蘋果和葡萄。其中一個(gè)水果店買白蘋果和白葡萄,另外一個(gè)水果店賣紅蘋果和紅葡萄。所以說(shuō),對(duì)于水果店而言,盡管都在賣水果,但是兩個(gè)店賣的品種不一樣。 既然水果不一樣,那我們先定義水果。typedef struct _Apple void (*print_apple)();Apple;typedef struct _Grape void (*print_grape)();Grape;上面分別對(duì)蘋果和葡萄進(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ù)的定義。下面就該定義工廠了,和水果一樣,我們也需要對(duì)工廠進(jìn)行抽象處理。typedef struct _FruitShop Apple* (*sell_apple)(); Grape * (*sell_grape)();FruitShop; 所以,對(duì)于賣白蘋果、白葡萄的水果店就該這樣設(shè)計(jì)了,紅蘋果、紅葡萄的水果店亦是如此。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)建工廠的時(shí)候,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.訪問(wèn)者模式不知不覺(jué)當(dāng)中,我們就到了最后一種設(shè)計(jì)模式,即訪問(wèn)者模式。訪問(wèn)者模式,聽(tīng)上去復(fù)雜一些。但是,這種模式用簡(jiǎn)單的一句話說(shuō),就是不同的人對(duì)不同的事物有不同的感覺(jué)。比如說(shuō)吧,豆腐可以做成麻辣豆腐,也可以做成臭豆腐??墒?,不同的地方的人未必都喜歡這兩種豆腐。四川的朋友可能更喜歡辣豆腐,江浙的人就可能對(duì)臭豆腐更喜歡一些。那么,這種情況應(yīng)該怎么用設(shè)計(jì)模式表達(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é)議交互中使用得比較多的模式。比如說(shuō),在不同的協(xié)議中,都會(huì)存在啟動(dòng)、保持、中止等基本狀態(tài)。那么怎么靈活地轉(zhuǎn)變這些狀態(tài)就是我們需要考慮的事情。假設(shè)現(xiàn)在有一個(gè)state, 說(shuō)明一下,這里定義了兩個(gè)變量,分別process函數(shù)和change_state函數(shù)。其中proces函數(shù)就是普通的數(shù)據(jù)操作,void normal_process() printf(normal process!n); change_state函數(shù)本質(zhì)上就是確定下一個(gè)狀態(tài)是什么。所以,在context中,應(yīng)該有一個(gè)state變量,還應(yīng)該有一個(gè)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í)行者分開(kāi)。老規(guī)矩,舉個(gè)范例吧。假設(shè)李老板是一家公司的頭兒,他現(xiàn)在讓他的秘書王小姐去送一封信。王小姐當(dāng)然不會(huì)自己親自把信送到目的地,她會(huì)把信交給郵局來(lái)完成整個(gè)投遞的全過(guò)程?,F(xiàn)在,我們就對(duì)投遞者、命令、發(fā)令者分別作出定義。首先定義post的相關(guān)數(shù)據(jù)。typedef struct _Post void (*do)(struct _Post* pPost); Post;Post完成了實(shí)際的投遞工作,那么命令呢?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í)行者分開(kāi)。老規(guī)矩,舉個(gè)范例吧。假設(shè)李老板是一家公司的頭兒,他現(xiàn)在讓他的秘書王小姐去送一封信。王小姐當(dāng)然不會(huì)自己親自把信送到目的地,她會(huì)把信交給郵局來(lái)完成整個(gè)投遞的全過(guò)程?,F(xiàn)在,我們就對(duì)投遞者、命令、發(fā)令者分別作出定義。首先定義post的相關(guān)數(shù)據(jù)。typedef struct _Post void (*do)(struct _Post* pPost); Post;Post完成了實(shí)際的投遞工作,那么命令呢?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.備忘錄模式 備忘錄模式的起源來(lái)自于撤銷的基本操作。有過(guò)word軟件操作經(jīng)驗(yàn)的朋友,應(yīng)該基本上都使用過(guò)撤銷的功能。舉個(gè)例子,假設(shè)你不小心刪除了好幾個(gè)段落的文字,這時(shí)候你應(yīng)該怎么辦呢?其實(shí)要做的很簡(jiǎn)單,單擊一些【撤銷】就可以全部搞定了。撤銷按鈕給我們提供了一次反悔的機(jī)會(huì)。既然是撤銷,那么我們?cè)谶M(jìn)行某種動(dòng)作的時(shí)候,就應(yīng)該創(chuàng)建一個(gè)相應(yīng)的撤銷操作?這個(gè)撤銷操作的相關(guān)定義可以是這樣的。typedef struct _Action int type; struct _Action* next; void* pData; void (*process)(void* pData);Action;數(shù)據(jù)結(jié)構(gòu)中定義了兩個(gè)部分:撤銷的數(shù)據(jù)、恢復(fù)的操作。那么這個(gè)撤銷函數(shù)應(yīng)該有一個(gè)創(chuàng)建的函數(shù),還有一個(gè)恢復(fù)的函數(shù)。所以,作為撤銷動(dòng)作的管理者應(yīng)該包括,既然數(shù)據(jù)在創(chuàng)建和修改的過(guò)程中都會(huì)有相應(yīng)的恢復(fù)操作,那么要是真正恢復(fù)原來(lái)的數(shù)據(jù)也就變得非常簡(jiǎn)單了。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.觀察者模式 觀察者模式可能是我們?cè)谲浖_(kāi)發(fā)中使用得比較多的一種設(shè)計(jì)模式。為什么這么說(shuō)?大家可以聽(tīng)我一一到來(lái)。我們知道,在windows的軟件中,所有的界都是由窗口構(gòu)成的。對(duì)話框是窗口,菜單是窗口,工具欄也是窗口。那么這些窗口,在很多情況下要對(duì)一些共有的信息進(jìn)行處理。比如說(shuō),窗口的放大,窗口的減小等等。面對(duì)這一情況,觀察者模式就是不錯(cuò)的一個(gè)選擇。首先,我們可以對(duì)這些共有的object進(jìn)行提煉。既然Observer在創(chuàng)建的時(shí)候就把自己綁定在某一個(gè)具體的Object上面,那么Object發(fā)生改變的時(shí)候,統(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.橋接模式 在以往的軟件開(kāi)發(fā)過(guò)程中,我們總是強(qiáng)調(diào)模塊之間要低耦合,模塊本身要高內(nèi)聚。那么,可以通過(guò)哪些設(shè)計(jì)模式來(lái)實(shí)現(xiàn)呢?橋接模式就是不錯(cuò)的一個(gè)選擇。我們知道,在現(xiàn)實(shí)的軟件開(kāi)發(fā)過(guò)程當(dāng)中,用戶的要求是多種多樣的。比如說(shuō),有這么一個(gè)餃子店吧。假設(shè)餃子店原來(lái)只賣肉餡的餃子,可是后來(lái)一些吃素的顧客說(shuō)能不能做一些素的餃子。聽(tīng)到這些要求的老板自然不敢怠慢,所以也開(kāi)始賣素餃子。之后,又有顧客提出,現(xiàn)在的肉餡餃子只有豬肉的,能不能做點(diǎn)牛肉、羊肉餡的餃子?一些只吃素的顧客也有意見(jiàn)了,他們建議能不能增加一些素餡餃子的品種,什么白菜餡的、韭菜餡的,都可以做一點(diǎn)。由此看來(lái),顧客的要求是一層一層遞增的。關(guān)鍵是我們?nèi)绾伟杨櫩偷囊蠛臀覀兊膶?shí)現(xiàn)的接口進(jìn)行有效地分離呢?上面只是對(duì)餃子進(jìn)行歸類。第一類是對(duì)肉餡餃子的歸類,第二類是對(duì)素餡餃子的歸類,這些地方都沒(méi)有什么特別之處。那么,關(guān)鍵是我們?cè)趺窗阉皖櫩偷囊舐?lián)系在一起呢?typedef struct _DumplingReuqest int type; void* pDumpling; DumplingRequest;這里定義了一個(gè)餃子買賣的接口。它的特別支持就在于兩個(gè)地方,第一是我們定義了餃子的類型type,這個(gè)type是可以隨便擴(kuò)充的;第二就是這里的pDumpling是一個(gè)void*指針,只有把它和具體的dumpling綁定才會(huì)衍生出具體的含義。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.建造者模式 如果說(shuō)前面的工廠模式是對(duì)接口進(jìn)行抽象化處理,那么建造者模式更像是對(duì)流程本身的一種抽象化處理。這話怎么理解呢?大家可以聽(tīng)我慢慢到來(lái)。以前買電腦的時(shí)候,大家都喜歡自己組裝機(jī)器。一方面可以滿足自己的個(gè)性化需求,另外一方面也可以在價(jià)格上得到很多實(shí)惠。但是電腦是由很多部分組成的,每個(gè)廠家都只負(fù)責(zé)其中的一部分,而且相同的組件也有很多的品牌可以從中選擇。這對(duì)于我們消費(fèi)者來(lái)說(shuō)當(dāng)然非常有利,那么應(yīng)該怎么設(shè)計(jì)呢? typedef struct _AssemblePersonalComputer void (*assemble_cpu)(); void (*assemble_memory)(); void (*assemble_harddisk)();AssemblePersonalComputer;對(duì)于一個(gè)希望配置intel cpu,samsung 內(nèi)存、日立硬盤的朋友。他可以這么設(shè)計(jì),14.中介者模式 中介者模式,聽(tīng)上去有一點(diǎn)陌生。但是,只要我給朋友們打個(gè)比方就明白了。早先自由戀愛(ài)沒(méi)有現(xiàn)在那么普遍的時(shí)候,男女之間的相識(shí)還是需要通過(guò)媒婆之間才能相互認(rèn)識(shí)。男孩對(duì)女方有什么要求,可以通過(guò)媒婆向女方提出來(lái);當(dāng)然,女方有什么要求也可以通過(guò)媒婆向男方提出來(lái)。所以,中介者模式在我看來(lái),就是媒婆模式。 typedef struct _Mediator People* man; People* woman; Mediator;上面的數(shù)據(jù)結(jié)構(gòu)是給媒婆的,那么當(dāng)然還有一個(gè)數(shù)據(jù)結(jié)構(gòu)是給男方、女方的。typedef struct _People Mediator* pMediator; void (*request)(struct _People* pPeople); void (*process)(struct _Peoplle* pPeople);People;所以,這里我們看到的如果是男方的要求,那么這個(gè)要求應(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)一的方法接口分別對(duì)不同類型的數(shù)據(jù)進(jìn)行訪問(wèn)。比如說(shuō),現(xiàn)在我們想用pc看一部電影,此時(shí)應(yīng)該怎么做呢?看電影嘛,當(dāng)然需要各種播放電影的方法。rmvb要rmvb格式的方法,avi要avi的方法,mpeg要mpeg的方法。可是事實(shí)上,我們完全可以不去管是什么文件格式。因?yàn)椴シ牌鲗?duì)所有的操作進(jìn)行了抽象,不同的文件會(huì)自動(dòng)調(diào)用相應(yīng)的訪問(wèn)方法。 typedef struct _MoviePlay struct _CommMoviePlay* pCommMoviePlay;MoviePlay;這個(gè)時(shí)候呢,對(duì)于用戶來(lái)說(shuō),統(tǒng)一的文件接口就是MoviePlay。接下來(lái)的一個(gè)工作,就是編寫一個(gè)統(tǒng)一的訪問(wèn)接口。void play_movie_file(struct MoviePlay* pMoviePlay) CommMoviePlay* pCommMoviePlay; assert(NULL != pMoviePlay); pCommMoviePlay = pMoviePlay-pCommMoviePlay; pCommMoviePlay-play(pCommMoviePlay-hFile); 最后的工作就是對(duì)不同的hFile進(jìn)行play的實(shí)際操作,寫簡(jiǎn)單一點(diǎn)就是,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)中,我們離不開(kāi)各種電子工具。什么筆記本電腦、手機(jī)、mp4啊,都離不開(kāi)充電。既然是充電,那么就需要用到充電器。其實(shí)從根本上來(lái)說(shuō),充電器就是一個(gè)個(gè)普通的適配器。什么叫適配器呢,就是把220v、50hz的交流電壓編程512v的直流電壓。充電器就干了這么一件事情。那么,這樣的一個(gè)充電適配器,我們應(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(); ;通過(guò)上面的代碼,我們其實(shí)可以這樣理解。類voltage_12v表示我們的最終目的就是為了獲得一個(gè)12v的直流電壓。當(dāng)然獲得12v可以有很多的方法,利用適配器轉(zhuǎn)換僅僅是其中的一個(gè)方法。adapter表示適配器,它自己不能實(shí)現(xiàn)220v到12v的轉(zhuǎn)換工作,所以需要調(diào)用類v220_to_v12的轉(zhuǎn)換函數(shù)。所以,我們利用adapter獲得12v的過(guò)程,其實(shí)就是調(diào)用v220_to_v12函數(shù)的過(guò)程。 不過(guò),既然我們的主題是用c語(yǔ)言來(lái)編寫適配器模式,那么我們就要實(shí)現(xiàn)最初的目標(biāo)。這其實(shí)也不難,關(guān)鍵一步就是定義一個(gè)Adapter的數(shù)據(jù)結(jié)構(gòu)。然后把所有的Adapter工作都由Adaptee來(lái)做,就是這么簡(jiǎn)單。不知我說(shuō)明白了沒(méi)有?typdef struct _Adaptee void (*real_process)(struct _Adaptee* pAdaptee);Adaptee;17.裝飾模式 裝飾模式是比較好玩,也比較有意義。其實(shí)就我個(gè)人看來(lái),它和責(zé)任鏈還是蠻像的。只不過(guò)一個(gè)是比較判斷,一個(gè)是迭代處理。裝飾模式就是那種迭代處理的模式,關(guān)鍵在哪呢?我們可以看看數(shù)據(jù)結(jié)構(gòu)。 typedef struct _Object struct _Object* prev; void (*decorate)(struct _Object* pObject);Object;裝飾模式最經(jīng)典的地方就是把pObject這個(gè)值放在了數(shù)據(jù)結(jié)構(gòu)里面。當(dāng)然,裝飾模式的奧妙還不僅僅在這個(gè)地方,還有一個(gè)地方就是迭代處理。我們可以自己隨便寫一個(gè)decorate函數(shù)試試看,void decorate(struct _Object* pObeject) assert(NULL != pObject); if(NULL != pObject-prev) pObject-prev-decorate(pObject-prev); printf(normal decorate!n);所以,裝飾模式的最重要的兩個(gè)方面就體現(xiàn)在:prev參數(shù)和decorate迭代處理。18.亨元模式享元模式看上去有點(diǎn)玄乎,但是其實(shí)也沒(méi)有那么復(fù)雜。我們還是用示例說(shuō)話。比如說(shuō),大家在使用電腦的使用應(yīng)該少不了使用WORD軟件。使用WORD呢, 那就少不了設(shè)置模板。什么模板呢,比如說(shuō)標(biāo)題的模板,正文的模板等等。這些模板呢,又包括很多的內(nèi)容。哪些方面呢,比如說(shuō)字體、標(biāo)號(hào)、字距、行距、大小等等。 上面的Font表示了各種Font的模板形式。所以,下面的方法就是定制一個(gè)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即使對(duì)當(dāng)前的Font進(jìn)行判斷,如果Font存在,那么返回;否則創(chuàng)建一個(gè)新的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è)計(jì)模式。它的基本思路也不復(fù)雜。舉個(gè)例子來(lái)說(shuō),以前在學(xué)校上網(wǎng)的時(shí)候,并不是每一臺(tái)pc都有上網(wǎng)的權(quán)限的。比如說(shuō),現(xiàn)在有pc1、pc2、pc3,但是只有pc1有上網(wǎng)權(quán)限,但是pc2、pc3也想上網(wǎng),此時(shí)應(yīng)該怎么辦呢? 此時(shí),我們需要做的就是在pc1上開(kāi)啟代理軟件,同時(shí)把pc2、pc3的IE代理指向pc1即可。這個(gè)時(shí)候,如果pc2或者pc3想上網(wǎng),那么報(bào)文會(huì)先指向pc1,然后pc1把Internet傳回的報(bào)文再發(fā)給pc2或者pc3。這樣一個(gè)代理的過(guò)程就完成了整個(gè)的上網(wǎng)過(guò)程。在說(shuō)明完整的過(guò)程之后,我們可以考慮一下軟件應(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); 這個(gè)時(shí)候,代理的操作應(yīng)該怎么寫呢?怎么處理來(lái)自各個(gè)協(xié)議的請(qǐng)求呢?typedef struct _Proxy PC_Client* pClient;Proxy;void process(Proxy* pProxy) assert(NULL != pProxy); pProxy-pClient-request();20.外觀模式 外觀模式是比較簡(jiǎn)單的模式。它的目的也是為了簡(jiǎn)單。什么意思呢?舉個(gè)例子吧。以前,我們逛街的時(shí)候吃要到小吃一條街,購(gòu)物要到購(gòu)物一條街,看書、看電影要到文化一條街。那么有沒(méi)有這樣的地方,既可以吃喝玩樂(lè),同時(shí)相互又靠得比較近呢。其實(shí),這就是悠閑廣場(chǎng),遍布全國(guó)的萬(wàn)達(dá)廣場(chǎng)就是干了這么一件事。首先,我們?cè)瓉?lái)是怎么做的。typedef struct _ShopStreet void (*buy)();ShopStreet;void buy() printf(buy here!n);typedef struct _BookStreet void (*read)();BookStreet;void read() printf(read here); 下面,我們就要在一個(gè)plaza里面完成所有的項(xiàng)目,怎么辦呢?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.迭代器模式 使用過(guò)C+的朋友大概對(duì)迭代器模式都不會(huì)太陌生。這主要是因?yàn)槲覀冊(cè)诰帉懘a的時(shí)候離不開(kāi)迭代器,隊(duì)列有迭代器,向量也有迭代器。那么,為什么要迭代器呢?這主要是為了提煉一種通用的數(shù)據(jù)訪問(wèn)方法。比如說(shuō),現(xiàn)在有一個(gè)數(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. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 信息教育活動(dòng)方案
- 修車店夏季活動(dòng)方案
- 俱樂(lè)部日?;顒?dòng)方案
- 借書閱讀活動(dòng)方案
- 傾心幫扶活動(dòng)方案
- 假期促銷活動(dòng)方案
- 假期打卡活動(dòng)方案
- 假期集訓(xùn)活動(dòng)方案
- 做了實(shí)踐活動(dòng)方案
- 健康大賽活動(dòng)方案
- 皮膚型紅斑狼瘡診療指南(2023年版)
- 高中化學(xué)競(jìng)賽預(yù)賽試卷
- 檔煙垂壁驗(yàn)收規(guī)范
- 《視覺(jué)傳達(dá)設(shè)計(jì)研究5000字(論文)》
- YY/T 0676-2008眼科儀器視野計(jì)
- 通信工程建設(shè)強(qiáng)制性標(biāo)準(zhǔn)條文培訓(xùn)材料(第1-3章)
- SB/T 10654-2012茶館經(jīng)營(yíng)服務(wù)規(guī)范
- “三重一大”事項(xiàng)決策情況記錄表
- 2022年山西蘭花太行中藥有限公司招聘筆試試題及答案解析
- 審計(jì)法知識(shí)講座課件
- 幼兒園小班科學(xué)教案《吹泡泡》
評(píng)論
0/150
提交評(píng)論