版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、設(shè)計(jì)模式學(xué)習(xí)總結(jié)引子剛開(kāi)始學(xué)習(xí)設(shè)計(jì)模式的時(shí)候,感到這些模式真的非常抽象。今年下半年以來(lái),隨著我們組工作重點(diǎn)的轉(zhuǎn)移,以及我在小組中角色的變化,我開(kāi)始有條件提出自己對(duì)新系統(tǒng)的設(shè)計(jì)想法。在設(shè)計(jì)過(guò)程中,我發(fā)現(xiàn)了很多設(shè)計(jì)模式的用處,也確實(shí)應(yīng)用了很多設(shè)計(jì)模式,這讓我越來(lái)越感到設(shè)計(jì)模式的重要性,因此我寫(xiě)了這十余篇專(zhuān)門(mén)介紹設(shè)計(jì)模式的文章,作為我的學(xué)習(xí)筆記。設(shè)計(jì)模式可復(fù)用的面向?qū)ο筌浖幕A(chǔ)(有趣的是,梅宏一再在組會(huì)上強(qiáng)調(diào)應(yīng)該譯成重用)中介紹了一共23種設(shè)計(jì)模式,我一共寫(xiě)了19個(gè)設(shè)計(jì)模式(其中三個(gè)和在一篇文章中),余下四個(gè),考慮到該模式的應(yīng)用范圍我就沒(méi)有介紹。在寫(xiě)這些文章時(shí),其中的很多例子都是我在實(shí)踐中提煉出來(lái)
2、的,當(dāng)然也有很大一部分是設(shè)計(jì)模式中的例子。不過(guò),這四個(gè)人(四人團(tuán))生活的年代里現(xiàn)在已經(jīng)很遠(yuǎn)了,所以它們的例子也很古老。讓我們更加設(shè)計(jì)模式設(shè)計(jì)模式是個(gè)好東西,它給出了很多設(shè)計(jì)中的技巧與思路,對(duì)于很多優(yōu)秀的設(shè)計(jì),它加以總結(jié)與提煉。設(shè)計(jì)模式并非四人團(tuán)拍腦瓜想出來(lái)的,而是他們搜集了其他人優(yōu)秀的設(shè)計(jì),加以整理出來(lái)的,他們不是這些模式的創(chuàng)造者,僅僅是整理者。應(yīng)用設(shè)計(jì)模式會(huì)給我們帶來(lái)很多好處:軟件將變得更加靈活,模塊之間的耦合度將會(huì)降低,效率會(huì)提升,開(kāi)銷(xiāo)會(huì)減少。更重要的,設(shè)計(jì)模式就好像美聲唱法中的花腔,讓你的設(shè)計(jì)更加漂亮??偟膩?lái)說(shuō),設(shè)計(jì)模式似乎將軟件設(shè)計(jì)提升到藝術(shù)的層次。設(shè)計(jì)模式已經(jīng)被廣泛的應(yīng)用了,在現(xiàn)在很
3、多的圖形界面框架都使用了MVC模式,大量跌代器模式的應(yīng)用,徹底改變了我們對(duì)集合的操作方式。不僅如此,應(yīng)用了設(shè)計(jì)模式的設(shè)計(jì),往往被看成為優(yōu)秀的設(shè)計(jì)。這是因?yàn)椋@些設(shè)計(jì)模式都是久經(jīng)考驗(yàn)的。模式不是模型在學(xué)習(xí)和使用設(shè)計(jì)模式的時(shí)候,往往出現(xiàn)一個(gè)非常嚴(yán)重的誤區(qū),那就是設(shè)計(jì)模式必須嚴(yán)格地遵守,不能修改。但是設(shè)計(jì)模式不是設(shè)計(jì)模型,并非一成不變。正相反,設(shè)計(jì)模式中最核心的要素并非設(shè)計(jì)的結(jié)構(gòu),而是設(shè)計(jì)的思想。只有掌握住設(shè)計(jì)模式的核心思想,才能正確、靈活的應(yīng)用設(shè)計(jì)模式,否則再怎么使用設(shè)計(jì)模式,也不過(guò)是生搬硬套。當(dāng)然,掌握設(shè)計(jì)模式的思想,關(guān)鍵是要仔細(xì)研究模式的意圖和結(jié)構(gòu)。一個(gè)模式的意圖,就是使用這個(gè)設(shè)計(jì)模式的目的,
4、體現(xiàn)了為什么要使用這個(gè)模式,也就是需求問(wèn)題。這個(gè)模式的結(jié)構(gòu),就是如何去解決這個(gè)問(wèn)題,是一種手段、一種經(jīng)典的解決方法,這種解決方法只是一種建議。兩個(gè)方面結(jié)合起來(lái),明白為什么需要設(shè)計(jì)模式,同時(shí)明白了如何實(shí)現(xiàn)這個(gè)模式,就容易抓住模式的本質(zhì)思想。在抓住意圖和結(jié)構(gòu)的基礎(chǔ)上,實(shí)踐也是掌握設(shè)計(jì)模式的必要方法。當(dāng)然,設(shè)計(jì)模式必須在某個(gè)場(chǎng)景下得到應(yīng)用才有意義,這也是為什么設(shè)計(jì)模式中提供了大量的例子用來(lái)說(shuō)明模式的應(yīng)用場(chǎng)景,這實(shí)際上為讀者提供了一種上下文環(huán)境。學(xué)外語(yǔ)不是要強(qiáng)調(diào)“語(yǔ)言環(huán)境”么,學(xué)習(xí)設(shè)計(jì)模式也是這樣。不要設(shè)計(jì)模式看到網(wǎng)上很多人在討論設(shè)計(jì)模式,他們確實(shí)很有*,滿嘴都是模式的名字,恨不得寫(xiě)個(gè)Hello Wo
5、rld都要應(yīng)用到設(shè)計(jì)模式。設(shè)計(jì)模式確實(shí)是好東西,但是,中國(guó)有句古話叫作物極必反,即便是按照辯證法,事物總要一分為二的看。我們說(shuō)設(shè)計(jì)模式的目的是為了讓軟件更加靈活,重用度更高。但是,某種意義上,設(shè)計(jì)模式增加了軟件維護(hù)的難度,特別是它增加了對(duì)象之間關(guān)聯(lián)的復(fù)雜度。我們總說(shuō),重用可以提高軟件開(kāi)發(fā)的效率。如果你是大牛,你自然希望你的設(shè)計(jì)可以被反復(fù)使用10000年,那就是:當(dāng)世界毀滅的時(shí)候,你的設(shè)計(jì)依然存在。然而,現(xiàn)實(shí)是一個(gè)系統(tǒng)的設(shè)計(jì)往往在5年之內(nèi)就會(huì)被拋棄,這是因?yàn)椋?,軟件技術(shù)產(chǎn)生了新的變化,使用新的技術(shù)進(jìn)行的設(shè)計(jì),無(wú)論如何都比你的設(shè)計(jì)好;2,硬件環(huán)境發(fā)生了很大變化,你的設(shè)計(jì)里對(duì)開(kāi)銷(xiāo)或者效率的追求已經(jīng)
6、沒(méi)有意義了;3,新的大牛出現(xiàn)了,并且取代了你的位置。應(yīng)用設(shè)計(jì)模式會(huì)導(dǎo)致設(shè)計(jì)周期的加長(zhǎng)(因?yàn)楦鼜?fù)雜了),但是很多項(xiàng)目還在設(shè)計(jì)階段就已經(jīng)胎死腹中,再好的設(shè)計(jì)也沒(méi)有發(fā)揮的余地。當(dāng)我們向設(shè)計(jì)模式頂禮膜拜的時(shí)候,我們還必須清醒地看到軟件生產(chǎn)中非技術(shù)層面上的東西往往具有決定性作用。理想固然崇高,但現(xiàn)實(shí)總是殘酷的。如何看清理想與現(xiàn)實(shí)的界限,恐怕是需要我們?cè)趯?shí)踐中不斷磨礪而體會(huì)出來(lái)的。在看完設(shè)計(jì)模式后,不妨反問(wèn)以下自己,這些模式究竟能給你帶來(lái)什么?Interpreter、Iterator、State模式 Interpreter模式:這個(gè)模式主要試圖去解釋一種語(yǔ)言。如果你學(xué)過(guò)形式語(yǔ)言,那么這個(gè)模式對(duì)你來(lái)說(shuō)是多余
7、的。 Iterator模式:這個(gè)模式試圖隱藏集合的內(nèi)部表示,又同時(shí)可以使用戶依次訪問(wèn)集合中的元素?,F(xiàn)在STL和Java的跌代器就是應(yīng)用這個(gè)模式的結(jié)果。 State模式:這個(gè)模式的意圖是允許對(duì)象在其狀態(tài)改變時(shí)修改其行為,好像對(duì)象改變了。這個(gè)模式的應(yīng)用場(chǎng)景是當(dāng)對(duì)象的行為依賴于對(duì)象的狀態(tài)時(shí)。為了實(shí)現(xiàn)這個(gè)模式,我們可以為每個(gè)狀態(tài)下的行為實(shí)現(xiàn)一個(gè)類(lèi),當(dāng)對(duì)象的狀態(tài)發(fā)生改變,它調(diào)用不同狀態(tài)對(duì)象的實(shí)例方法。注意,以前可能需要使用switch或者if語(yǔ)句進(jìn)行分支轉(zhuǎn)換,現(xiàn)在則利用多態(tài)機(jī)制完成。Flyweight模式 這個(gè)模式利用共享有效的支持大量的細(xì)粒度的對(duì)象。比如,編輯軟件中,一篇文章有很多個(gè)字符,我們可以對(duì)每
8、個(gè)字符對(duì)象生成一個(gè)對(duì)象,如果這篇文章有幾M個(gè)文字,那么對(duì)象的數(shù)量肯定是不能容忍的。使用Flyweight模式,我們將所有的文字對(duì)象共享起來(lái),文章中的字符僅僅是指向共享池中的某個(gè)對(duì)象的索引。 在這里要搞清楚一件事情,利用Flyweight模式不會(huì)有效地減少信息的數(shù)量(也就是軟件的空間開(kāi)銷(xiāo)),因?yàn)闊o(wú)論是否共享,表達(dá)這么多信息所需要的編碼數(shù)量是一定的,所以開(kāi)銷(xiāo)不會(huì)大幅減小。只是,這個(gè)模式會(huì)減少系統(tǒng)中對(duì)象的數(shù)量,因?yàn)榇罅康膶?duì)象會(huì)被共享。 在編輯軟件中,字符對(duì)象被共享,那么一篇文章中的文字,可以按照段落、格式等等進(jìn)行結(jié)組,一組文字構(gòu)成一個(gè)對(duì)象,這樣對(duì)象從單個(gè)文字變成一組文字,數(shù)量大幅減少。 在使用Fly
9、weight模式需要注意的一點(diǎn),由于對(duì)象被共享了,因此這些對(duì)象沒(méi)有各自的屬性,那么根據(jù)上下文環(huán)境,我們?cè)谑褂眠@些對(duì)象的時(shí)候,必須向它傳遞一些參數(shù)。在編輯軟件中,這些參數(shù)可能就是字體、字號(hào)、顏色等等信息。 使用Flyweight模式還有一個(gè)好處,那就是我們可以在不修改系統(tǒng)的情況下增加享元。Command模式 Command模式,將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象。這樣,你可以向客戶端發(fā)送不同請(qǐng)求的參數(shù),排隊(duì)或記錄請(qǐng)求,同時(shí)可以支持不能執(zhí)行的請(qǐng)求。 在軟件中,不同的模塊、對(duì)象之間經(jīng)常會(huì)各種調(diào)用,或者我們稱(chēng)之為請(qǐng)求。傳統(tǒng)的方法,我們將請(qǐng)求實(shí)現(xiàn)為函數(shù)調(diào)用。這樣做是最簡(jiǎn)單的方法,但卻在無(wú)形之中增加了模塊之間的耦合
10、度。當(dāng)請(qǐng)求發(fā)生很大變化的時(shí)候,系統(tǒng)將變得很難維護(hù)。與此同時(shí),當(dāng)服務(wù)端(接受請(qǐng)求的一端)增加或者刪除一個(gè)請(qǐng)求的時(shí)候,按照傳統(tǒng)的方法,客戶端(發(fā)送請(qǐng)求的一端)也必須重新編譯(這一點(diǎn)在刪除請(qǐng)求的時(shí)候最明顯),這樣系統(tǒng)才能正確運(yùn)行。 使用Command模式的一個(gè)核心思想就是,服務(wù)端提供一個(gè)統(tǒng)一的請(qǐng)求處理接口,客戶端則通過(guò)調(diào)用接口向服務(wù)端發(fā)送請(qǐng)求,這些請(qǐng)求被封裝成對(duì)象的形式(或者其等價(jià)形式)。在設(shè)計(jì)模式中,“四人團(tuán)”并沒(méi)有強(qiáng)調(diào)統(tǒng)一接口的事情,它強(qiáng)調(diào)了另一個(gè)方面,那就是封裝請(qǐng)求。事實(shí)上,封裝一個(gè)請(qǐng)求總是要求有一個(gè)地方來(lái)接受和處理這個(gè)請(qǐng)求的,這個(gè)地方實(shí)際上就是統(tǒng)一請(qǐng)求接口。 在設(shè)計(jì)模式中,請(qǐng)求被封裝成一個(gè)C
11、ommand對(duì)象,這個(gè)對(duì)象保存著請(qǐng)求類(lèi)型、參數(shù)等信息,服務(wù)端收到這個(gè)命令后就會(huì)執(zhí)行Command對(duì)象中的Execute()函數(shù),這個(gè)函數(shù)具體實(shí)現(xiàn)了真正的操作。這種實(shí)現(xiàn)方法可以保證增加新的請(qǐng)求而不必重新編譯服務(wù)端。 我個(gè)人認(rèn)為,Command模式的另一個(gè)形式就是在服務(wù)端實(shí)現(xiàn)各種操作,Command對(duì)象只是負(fù)責(zé)指明請(qǐng)求的類(lèi)型,這樣,當(dāng)服務(wù)器端發(fā)現(xiàn)請(qǐng)求不正確時(shí),可以忽略該請(qǐng)求。和上一種形式相比,這種形式更加簡(jiǎn)潔(因?yàn)榭梢圆徽嬲龑?shí)現(xiàn)Command對(duì)象,在C+中可以使用不定參數(shù)實(shí)現(xiàn)),但是缺少靈活性。 Command模式使得記錄請(qǐng)求成為了可能,我們可以捕獲系統(tǒng)中的請(qǐng)求對(duì)象,記錄他們。Composite模
12、式 Composite模式的意圖是“將對(duì)象組合成樹(shù)形結(jié)構(gòu)表示整體-部分的層次結(jié)構(gòu)。Composite使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用更具有一致性”。 在Word中我們經(jīng)常會(huì)將一些圖元進(jìn)行“組合”,組合以后的圖形還可以向簡(jiǎn)單圖元那樣進(jìn)行移動(dòng)、變形等等操作;除此以外,在Word中,我們對(duì)于一個(gè)字符、一個(gè)詞組、一句話、一個(gè)段落,甚至是整篇文章的操作是相同的,我們都可以進(jìn)行剪切、復(fù)制,進(jìn)行字體與大小的調(diào)整,進(jìn)行顏色的變換。這些例子都是Composite模式的實(shí)例,我們將簡(jiǎn)單的元素組合成復(fù)雜的元素,然后還可以像操作簡(jiǎn)單元素那樣操作組合元素。 Composite模式將子元素組織成樹(shù)型,實(shí)際上,組織成圖型
13、也沒(méi)有問(wèn)題。用戶總是喜歡組合簡(jiǎn)單元素,一方面,用戶可以通過(guò)這樣的組合來(lái)進(jìn)行抽象,另一方面,用戶可以通過(guò)組合化簡(jiǎn)繁瑣的操作。Composite模式在各種可視化編輯軟件中應(yīng)用得最為廣泛。 另一使用Composite的經(jīng)典例子是Java的Swing系統(tǒng)。所有的Swing組件都是繼承自一個(gè)叫做JComponent的接口,因此,我們對(duì)一個(gè)JFrame的操作和對(duì)一個(gè)JButton的操作是一樣的。這同時(shí)也使得,JFrame在管理自己的子元素時(shí),它不需要知道他們是一個(gè)JButton還是一個(gè)JPanel,對(duì)它來(lái)說(shuō),這只是一個(gè)JComponent。 實(shí)現(xiàn)Composite模式的關(guān)鍵是良好設(shè)計(jì)的接口,人們應(yīng)該對(duì)可能
14、的元素(簡(jiǎn)單的、組合的)進(jìn)行分析,并設(shè)計(jì)出通用的操作。盡可能的保證接口操作對(duì)所有元素都是有意義的,否則就應(yīng)該將那些只對(duì)部分元素有意義的操作下放到子類(lèi)中。Proxy模式 按照“四人團(tuán)”的說(shuō)法,Proxy模式可以為控制另一個(gè)對(duì)象而提供一個(gè)代理或者占位符。 這個(gè)模式可以使我們?cè)谡嬲枰臅r(shí)候創(chuàng)建對(duì)象,如果我們不需要這個(gè)對(duì)象,Proxy模式會(huì)為我們提供一個(gè)占位符。如果我們有大量這樣消耗很大的對(duì)象的時(shí)候,我們就可以使用Proxy模式,初始情況下,Proxy模式只會(huì)提供占位符而不會(huì)真正創(chuàng)建對(duì)象,但是對(duì)于使用者來(lái)說(shuō),他看到是真正的對(duì)象而不是一個(gè)代理。一旦使用者需要獲得或者更改對(duì)象屬性的時(shí)候,Proxy模式就
15、會(huì)創(chuàng)建該對(duì)象,在此之后,我們就可以通過(guò)代理訪問(wèn)真正的對(duì)象了。 在Word里面應(yīng)該是使用了Proxy模式。打開(kāi)一篇含圖的很長(zhǎng)的文檔時(shí),大部分的圖片都不會(huì)被載入,而僅僅是提供占位符,只有當(dāng)用戶準(zhǔn)備察看這一頁(yè)的時(shí)候,代理才會(huì)真正載入圖片。 和Singleton模式一樣,Proxy模式都是保證我們可以按需分配對(duì)象,不同的是,Singleton模式還會(huì)保證在全局范圍內(nèi)使用同一個(gè)對(duì)象實(shí)例,而Proxy則沒(méi)有這個(gè)功能。Visitor模式 按照“四人團(tuán)”的說(shuō)法,Visitor模式的意圖為:將元素的操作表示成一種結(jié)構(gòu)。這樣Visitor模式可以使你在不修改元素結(jié)構(gòu)的前提下增加新的操作。 考慮一個(gè)鏈表,我們需要一
16、個(gè)求得最大元素的操作,這個(gè)操作可能是遍歷每個(gè)節(jié)點(diǎn),然后求的最大值。這個(gè)時(shí)候我們又需要一個(gè)為每個(gè)元素加1的操作,這個(gè)操作還需要遍歷每個(gè)節(jié)點(diǎn),同時(shí)將每個(gè)元素加1。與之類(lèi)似,還會(huì)有很多其他的針對(duì)元素操作,他們的特點(diǎn)都是要遍歷鏈表。這個(gè)時(shí)候可以使用Visitor模式,結(jié)點(diǎn)類(lèi)負(fù)責(zé)依次遍歷,并調(diào)用Visitor類(lèi)中的函數(shù),而Visitor類(lèi)的具體實(shí)現(xiàn)則負(fù)責(zé)完成功能。 這里需要注意的是,Visitor類(lèi)只能是一個(gè)接口,針對(duì)不同的操作需要有不同的具體實(shí)現(xiàn),針對(duì)不同的具體元素,需要設(shè)計(jì)不同的操作。每個(gè)元素負(fù)責(zé)選擇自己應(yīng)該調(diào)用的操作,Visitor子類(lèi)負(fù)責(zé)實(shí)現(xiàn)具體功能。 一個(gè)已知的應(yīng)用是SmallTalk-80的
17、編譯器,在編譯時(shí),編譯器需要建立一棵語(yǔ)法樹(shù)。在這個(gè)時(shí)候,它使用了Visitor模式,針對(duì)不同的操作,比如:類(lèi)型檢查、代碼生成等操作實(shí)現(xiàn)不同的Visitor具體類(lèi),Visitor類(lèi)中針對(duì)不同的節(jié)點(diǎn)類(lèi)型提供不同的操作接口,具體的節(jié)點(diǎn)負(fù)責(zé)選擇調(diào)用哪種接口,這像是一種回調(diào)操作。Observer模式 按照“四人團(tuán)”的說(shuō)法,Observer模式的意圖是“定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新”。 實(shí)際應(yīng)用的例子是,比如建模工具中,若干條線形元素附著在一個(gè)塊狀元素上,當(dāng)塊狀元素的大小、位置發(fā)生變化,那些線形元素也需要進(jìn)行改變,這個(gè)時(shí)候我們就可以
18、應(yīng)用Observer模式,在塊狀元素和線形元素之間建立一對(duì)多的關(guān)系,并利用這一模式進(jìn)行維護(hù)。 Observer模式首先構(gòu)造一個(gè)Observer類(lèi),在這個(gè)類(lèi)中具有一個(gè)update函數(shù)。被依賴的對(duì)象擁有它,依賴的對(duì)象被注冊(cè)到Observer中,當(dāng)被依賴的對(duì)象發(fā)生變化的時(shí)候,就調(diào)用update函數(shù)更新所有依賴它的對(duì)象。更新的方式由update函數(shù)具體實(shí)現(xiàn)。 還有一個(gè)現(xiàn)實(shí)中的例子,各個(gè)部門(mén)之間進(jìn)行通訊,當(dāng)一方發(fā)出新的信息時(shí),按照傳統(tǒng)的方法它必須告訴所有其他部門(mén)。如果使用Observer模式,那么產(chǎn)生新消息的一方只需要告知Observer,由Observer通知其他方面。TemplateMethod模式
19、 Template Method模式的意圖是:“定義一個(gè)操作中的骨架,而將一些步驟延遲到子類(lèi)中。這使得子類(lèi)可以不改變一個(gè)算法的結(jié)構(gòu)即可以重定義該算法的某些特定步驟。 這一模式和Strategy模式似乎和相似,但是他們的關(guān)注點(diǎn)不同。策略模式主要用于算法的替換,但是模板方法模式主要用于算法中特定步驟地替換。一個(gè)應(yīng)用模板方法模式的例子是數(shù)據(jù)庫(kù)操作。對(duì)于數(shù)據(jù)庫(kù)操作可以有很多中,比如查詢、更新。查詢又可以分為連接數(shù)據(jù)庫(kù)、發(fā)送請(qǐng)求命令、解析結(jié)果等等步驟。對(duì)于不同的數(shù)據(jù)庫(kù),比如Oracle和SQL2000,它們連接數(shù)據(jù)庫(kù)、命令格式可能有所不同,但是就查詢和更新著兩個(gè)操作來(lái)說(shuō)它們的步驟是相同的。這個(gè)時(shí)候,我們
20、可以應(yīng)用模板方法模式,為查詢、更新操作建立一個(gè)抽象的算法,具體的步驟交給子類(lèi)來(lái)實(shí)現(xiàn)。如果對(duì)于策略模式,我們替換的將是查詢和更新著兩個(gè)操作。 但是,將Template Method模式和Strategy模式進(jìn)行類(lèi)比是危險(xiǎn)的,這兩個(gè)模式有著很多重要的不同,但這些不同卻又是十分的細(xì)微,只能意會(huì)不能言傳。FactoryMethod模式 這一模式的意圖是:“定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類(lèi)決定實(shí)例化哪一個(gè)類(lèi)。Factory Method是一個(gè)類(lèi)的實(shí)例化延遲到其子類(lèi)。” 這一模式的關(guān)鍵是掌握“何時(shí)應(yīng)用這一模式”,事實(shí)上我覺(jué)得這也是所有設(shè)計(jì)模式的關(guān)鍵。一個(gè)已知的應(yīng)用就是MFC中關(guān)于Document和Fra
21、me之間的關(guān)系。通常在生成一個(gè)多文檔程序時(shí),VC會(huì)為你創(chuàng)建一個(gè)Frame類(lèi)和Document類(lèi),你的Frame類(lèi)可以用來(lái)相應(yīng)OnFileNew消息,然后創(chuàng)建一個(gè)Document對(duì)象。但是對(duì)于Windows的消息系統(tǒng)來(lái)說(shuō),它并不知道用戶程序中創(chuàng)建的Document類(lèi)有什么特性,對(duì)于它來(lái)說(shuō),它所看到是CFrame對(duì)象和CDocument對(duì)象。Factory Method模式可以保證其他對(duì)象不需要知道具體對(duì)象的類(lèi)型而管理這些對(duì)象,這一模式通常用于制定框架。 這一模式和Abstract Factory模式很相像,事實(shí)上Abstract Factory模式可以由一系列Factory Method模式實(shí)現(xiàn)
22、。Strategy模式 Strategy模式的目的就是“定義一系列的算法,把他們一個(gè)個(gè)封裝起來(lái),并且使他們可以互相替換。” 如何理解這一模式,首先看下面這個(gè)場(chǎng)景:一組數(shù)據(jù)進(jìn)行排序,我們可以選擇很多中排序算法,這個(gè)時(shí)候我們定義一個(gè)排序策略,然后每個(gè)排序算法實(shí)現(xiàn)一個(gè)具體策略,這樣用戶就可以在幾個(gè)不同的排序算法中隨意選擇和替換了。 當(dāng)然,上面的例子中使用策略模式似乎多此一舉,那么假設(shè)游戲中的敵人的AI,根據(jù)玩家的設(shè)定可以有不同的級(jí)別。在這種情況下,使用策略模式就是十分必要的了。Bridge模式 按照“四人團(tuán)”的說(shuō)法,Bridge模式的意圖是:將抽象部分與他的實(shí)現(xiàn)部分分離,使得他們可以獨(dú)立的變化。你一
23、定會(huì)感到一陣眩暈,不明白這是什么意思。 首先應(yīng)該說(shuō)明的是“抽象”與“實(shí)現(xiàn)”的含義。在剛才的那句話中,“抽象”與“實(shí)現(xiàn)”并不是我們?cè)诿枋鲱?lèi)結(jié)構(gòu)時(shí)所說(shuō)的“接口”與它的“實(shí)現(xiàn)”,或者在Java中抽象類(lèi)與他的實(shí)現(xiàn)。在這里,“抽象”與“實(shí)現(xiàn)”只得是某種工作,“抽象”是說(shuō)如何完成這項(xiàng)工作,“實(shí)現(xiàn)”是說(shuō)“抽象”中所用的步驟的實(shí)現(xiàn)。 一個(gè)例子可以很好的說(shuō)明“抽象”與“實(shí)現(xiàn)”的關(guān)系。我們編寫(xiě)一個(gè)游戲,這個(gè)游戲有兩個(gè)版本,DX版本和OpenGL版本。我們?nèi)绾尉帉?xiě)這兩個(gè)版本呢?一種方法是我們?cè)谶@兩個(gè)引擎上開(kāi)發(fā)兩套獨(dú)立的游戲,但這顯然不是最好的方法。另一個(gè)選擇是我們將游戲的“抽象”部分與“實(shí)現(xiàn)”部分分離,開(kāi)發(fā)一套“抽
24、象”部分,開(kāi)發(fā)兩套“實(shí)現(xiàn)”部分。那么什么是游戲的“抽象”部分?很顯然就是游戲的繪圖(也許用更專(zhuān)業(yè)詞匯的應(yīng)該是:渲染)過(guò)程,例如我們?nèi)绾武秩居螒虻娜宋?,這個(gè)人物可能是由很多個(gè)多邊形組合而成的,我們按照一定的方法渲染之后,就可以畫(huà)出一個(gè)人物來(lái)。這一部分就可以看作是“抽象”。那么另一方面就是“實(shí)現(xiàn)”部分,在上面的例子中,“實(shí)現(xiàn)”部分就是如何繪制基礎(chǔ)的線條、填充顏色,甚至是初始化屏幕等等。這些“實(shí)現(xiàn)”和具體的引擎密切相關(guān)。 為什么說(shuō)我們可以將“抽象”和“實(shí)現(xiàn)”分離,使得他們可以各自變化呢?假設(shè)現(xiàn)在要開(kāi)發(fā)新的游戲,或者這個(gè)游戲升級(jí)了,在其中出現(xiàn)了新的人物,那么“抽象”部分就發(fā)生了變化,但是具體“實(shí)現(xiàn)”沒(méi)
25、有變化,因此這個(gè)游戲還可以繼續(xù)在你的計(jì)算機(jī)上運(yùn)行。另一方面,如果游戲需要進(jìn)行移植,目標(biāo)平臺(tái)的圖形系統(tǒng)發(fā)生了變化,你可能需要使用新的繪圖引擎,這個(gè)時(shí)候,你只需要利用新的引擎實(shí)現(xiàn)基本的“實(shí)現(xiàn)”操作,原始的程序就可以在新的平臺(tái)上運(yùn)行(略去重新編譯的問(wèn)題)。Facade模式 Facade模式的目的就是給子系統(tǒng)提供一個(gè)統(tǒng)一的接口。現(xiàn)在的軟件都是按照模塊進(jìn)行劃分,對(duì)不同的模塊分別進(jìn)行編程。但是在用戶開(kāi)來(lái),不同的模塊應(yīng)該具有統(tǒng)一的接口,換句話說(shuō),我們應(yīng)該可以通過(guò)統(tǒng)一的接口訪問(wèn)系統(tǒng)中的所有功能。 有一個(gè)很典型的例子就是編譯系統(tǒng)。通常我們將編譯系統(tǒng)分解為:Compile和Link兩個(gè)步驟。一個(gè)Compile又可
26、以分解為詞法分析、語(yǔ)法分析、語(yǔ)義分析、中間代碼生成等等步驟。對(duì)于用戶來(lái)講,我們不可能將這些模塊分別提供給他們,讓他們依次調(diào)用。相反的,我們應(yīng)該提供一個(gè)統(tǒng)一的接口,使得用戶可以方便的使用各個(gè)功能,例如IDE 。 Facade模式在強(qiáng)調(diào)模塊化開(kāi)發(fā)的同時(shí)也強(qiáng)調(diào)模塊的統(tǒng)一,統(tǒng)一的接口也有利于子系統(tǒng)中模塊內(nèi)部的變化。對(duì)于開(kāi)發(fā)大型系統(tǒng)來(lái)說(shuō),F(xiàn)acade模式是不可缺少的。Decorator模式 按照“四人團(tuán)”的說(shuō)法,Decorator模式的意圖是:動(dòng)態(tài)的給一個(gè)對(duì)象添加一些額外的職責(zé)。值得注意的是,這個(gè)對(duì)象不知道他增加的是什么職責(zé)。 這個(gè)模式的一個(gè)典型應(yīng)用實(shí)例是:Java的流。一個(gè)文件流(Java.IO.Fi
27、le)用于讀寫(xiě)文件,如果你想使用文件緩沖,你可在為File添加一個(gè)BufferedInputStream或者BufferedOutputStream外觀,這樣這個(gè)文件流就具有了緩沖。再如一個(gè)Reader類(lèi),你可以給他增加緩沖BufferedReader,然后你還可以給這個(gè)緩沖流增加一些格式化讀取的能力。 Decorator模式可以動(dòng)態(tài)的增加對(duì)象的額外的職責(zé),這也有利于將額外的功能分別實(shí)現(xiàn),使得用戶可以自由組合。Adapter模式 有一天你在網(wǎng)上找到一個(gè)庫(kù),你打算把它應(yīng)用到你的程序當(dāng)中去,但是你發(fā)現(xiàn)這個(gè)庫(kù)的函數(shù)不符合你的風(fēng)格,你會(huì)怎么辦?一個(gè)很簡(jiǎn)單的方法就是使用Adapter模式。 Adapte
28、r模式的目的就是將一個(gè)類(lèi)的接口轉(zhuǎn)換為用戶希望的接口,使得由于接口不兼容而不能一起工作的各個(gè)類(lèi)可以一起工作。 例如在一個(gè)軟件里面可能使用了以前一個(gè)版本的類(lèi)庫(kù)。不幸的是這個(gè)類(lèi)庫(kù)的效率極高卻和現(xiàn)在的接口不兼容,為了繼續(xù)復(fù)用這個(gè)類(lèi)庫(kù)我們就可以使用Adapter模式,在原來(lái)的類(lèi)庫(kù)和現(xiàn)在的接口中間實(shí)現(xiàn)一個(gè)適配器,使得我們可以用現(xiàn)在的結(jié)構(gòu)調(diào)用以前的類(lèi)庫(kù)。 例如一個(gè)繪圖程序(這種事情總是出現(xiàn)在這類(lèi)程序中),以前的類(lèi)庫(kù)中提供繪制直線的方法DrawLine,但是新的接口要求繪圖系統(tǒng)還要提供繪制矩形、折線形的方法,為了復(fù)用這個(gè)類(lèi)庫(kù),我們實(shí)現(xiàn)一個(gè)Adapter類(lèi),這個(gè)類(lèi)中利用以前的繪圖系統(tǒng)提供的方法實(shí)現(xiàn)了新的接口功能
29、。Singleton模式 這可能是最簡(jiǎn)單的一個(gè)模式了,但是他的應(yīng)用卻是最多的。這個(gè)模式的目的就是保證一個(gè)對(duì)象只有一個(gè)實(shí)例,并且提供一個(gè)全局的訪問(wèn)點(diǎn)。 那么這個(gè)模式的怎么實(shí)現(xiàn)呢?很簡(jiǎn)單,你首先必須為這個(gè)類(lèi)設(shè)置一個(gè)指針(Java中是引用),然后提供一個(gè)方法用來(lái)獲得這個(gè)類(lèi)的實(shí)例。在這個(gè)方法中首先判斷這個(gè)指針是否為空,如果是,則創(chuàng)建一個(gè)實(shí)例,否則直接返回這個(gè)指針。 雖然我們可以提供一個(gè)全局訪問(wèn)點(diǎn),但實(shí)際上這個(gè)模式也可以應(yīng)用到局部。應(yīng)用這個(gè)模式一個(gè)好處就是可以“按需分配”,同時(shí)也封裝了對(duì)象的獲取過(guò)程。不論如何,我覺(jué)得應(yīng)該盡可能的應(yīng)用這個(gè)模式,雖然這會(huì)讓你感到很煩 這個(gè)模式在實(shí)現(xiàn)過(guò)程中可以進(jìn)行變化,例如在
30、Instance()方法上添加參數(shù)Boolean bAlloc,用于指定當(dāng)實(shí)例不存在的時(shí)候是否進(jìn)行創(chuàng)建。這樣做是考慮到,有些時(shí)候我們獲得實(shí)例的目的不是為了修改,而是為了讀取。這個(gè)時(shí)候,返回一個(gè)空實(shí)例和返回一個(gè)沒(méi)有被修改過(guò)的實(shí)例在邏輯上是相同的。例如,這個(gè)對(duì)象是一個(gè)數(shù)組時(shí),一個(gè)“空數(shù)組”和一個(gè)“空白的數(shù)組”是相同的。Builder模式 按照“四人團(tuán)”的說(shuō)法,Builder模式的目的是:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與他的表示分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示。 一個(gè)典型的例子是:文件的格式轉(zhuǎn)換。假設(shè)一個(gè)RTF文件,我們可以將它轉(zhuǎn)換成不同的格式,比如TXT、DOC、PDF等等。在這些目標(biāo)格式的文件中,有些文件格式中保留文本字體(比如DOC),有些可能不保留(比如TXT)。當(dāng)我們開(kāi)始轉(zhuǎn)換過(guò)程時(shí),按照RTF文
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年中藥購(gòu)銷(xiāo)員(中級(jí))(理論知識(shí))試題及答案
- 2025年大學(xué)人體斷層解剖學(xué)(斷層結(jié)構(gòu)識(shí)別)試題及答案
- 2025年大學(xué)第四學(xué)年(歷史學(xué))世界近現(xiàn)代史綜合測(cè)試試題及答案
- 2025年高職編導(dǎo)(影視編導(dǎo))試題及答案
- 2025年大學(xué)生物(生物化學(xué))試題及答案
- 2025年中職(舞蹈表演)舞蹈基本功試題及答案
- 2025年高職藥品質(zhì)量與安全(藥品風(fēng)險(xiǎn)評(píng)估)試題及答案
- 2025年高職茶葉生產(chǎn)與應(yīng)用(茶葉營(yíng)銷(xiāo)實(shí)務(wù))試題及答案
- 2026年安徽審計(jì)職業(yè)學(xué)院高職單招職業(yè)適應(yīng)性測(cè)試備考題庫(kù)有答案解析
- 2026年貴州交通職業(yè)技術(shù)學(xué)院?jiǎn)握芯C合素質(zhì)筆試模擬試題帶答案解析
- GB/T 8642-2025熱噴涂抗拉結(jié)合強(qiáng)度的測(cè)定
- 貴州省貴陽(yáng)市2024-2025學(xué)年高一上學(xué)期期末監(jiān)測(cè)物理試卷(含解析)
- 2025河北省石家莊市公務(wù)員考試常識(shí)判斷專(zhuān)項(xiàng)練習(xí)題必考題
- 期末沖刺備考總動(dòng)員校長(zhǎng)在教師會(huì)議上講話:五字訣精實(shí)盯嚴(yán)穩(wěn)
- 裝修工程施工方案簡(jiǎn)單版
- 重慶市大渡口區(qū)2023年九年級(jí)第一次適應(yīng)性檢測(cè)數(shù)學(xué)試題【含答案】
- MT 236-1991組合鋼罐道滾輪罐耳
- LY/T 2488-2015實(shí)木拼接板
- GB/T 15543-2008電能質(zhì)量三相電壓不平衡
- 鐵路機(jī)車(chē)車(chē)輛課件
- 12鉆孔降水頭注水試驗(yàn)成果表2017-094gk
評(píng)論
0/150
提交評(píng)論