軟件設(shè)計(jì)原則與設(shè)計(jì)模式_第1頁(yè)
軟件設(shè)計(jì)原則與設(shè)計(jì)模式_第2頁(yè)
軟件設(shè)計(jì)原則與設(shè)計(jì)模式_第3頁(yè)
軟件設(shè)計(jì)原則與設(shè)計(jì)模式_第4頁(yè)
軟件設(shè)計(jì)原則與設(shè)計(jì)模式_第5頁(yè)
已閱讀5頁(yè),還剩211頁(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)介

設(shè)計(jì)原則與設(shè)計(jì)模式設(shè)計(jì)模式式的思想想根源是是基本原原則的宏宏觀運(yùn)用用,本質(zhì)上是是沒(méi)有任任何模式式的發(fā)現(xiàn)模式式的人永永遠(yuǎn)是大大師,而死守模模式的人人,最多只能能是一個(gè)個(gè)工匠.2設(shè)計(jì)模式式DesignPattern設(shè)計(jì)模式式DesignPattern面向?qū)ο笙笱芯康牡男骂I(lǐng)域域20世紀(jì)90年代,面面向?qū)ο笙蠓椒ㄅc與技術(shù)在在國(guó)內(nèi)軟軟件業(yè)界界十分火火爆,人人們熱衷衷于談?wù)撜摗皩?duì)象象”并引引以為榮榮。十多多年來(lái),,人們發(fā)發(fā)表、出出版了無(wú)無(wú)數(shù)的文文章和書(shū)書(shū)籍。現(xiàn)現(xiàn)在,該該寫(xiě)的似似乎都寫(xiě)寫(xiě)完了,,沒(méi)有新新花樣玩玩了,真真是一片片無(wú)聊設(shè)計(jì)模式式(DesignPattern))及時(shí)問(wèn)世世,面向向?qū)ο髳?ài)愛(ài)好者們們終于有有了新的的追求3設(shè)計(jì)模式式:起源源起源ChristopherAlexander當(dāng)代著名名建筑大大師加州大學(xué)學(xué)伯克利利分校建建筑學(xué)教教授、環(huán)環(huán)境結(jié)構(gòu)構(gòu)研究所所所長(zhǎng)、、美國(guó)藝藝術(shù)與科科學(xué)院院院士在建筑、、室內(nèi)、、計(jì)算機(jī)機(jī)、家具具設(shè)計(jì)甚甚至哲學(xué)學(xué)方面都都卓有建建樹(shù)著作:《APatternLanguage》、《TheTimelessWayofBuilding》4設(shè)計(jì)模式式:起源源Gof((GangOfFour,“四人人幫”)ErichGamma,RichardHelm,RalphJohnson,JohnVlissides1995年出版了了《DesignPatterns:ElementsofReusableObject--OrientedSoftware》》該書(shū)確立立了設(shè)計(jì)計(jì)模式這這個(gè)術(shù)語(yǔ)語(yǔ),創(chuàng)導(dǎo)導(dǎo)了一種種新的面面向?qū)ο笙笤O(shè)計(jì)思思潮。從從此,參參與設(shè)計(jì)計(jì)模式研研究的人人數(shù)爆炸炸性地增增長(zhǎng)5設(shè)計(jì)模式式:起源源6設(shè)計(jì)模式式什么叫模模式?“每一個(gè)個(gè)模式描描述了在在我們周周?chē)粩鄶嘀貜?fù)發(fā)發(fā)生的問(wèn)問(wèn)題,以以及該問(wèn)問(wèn)題的解解決方案案的核心心。這樣樣,你就就能一次次又一次次地使用用該解決決方案而而不必重重復(fù)勞動(dòng)動(dòng)”盡管軟件件技術(shù)發(fā)發(fā)展非常??欤侨匀蝗挥蟹浅36嗟脑O(shè)設(shè)計(jì)模式式可以讓讓我們套套用設(shè)計(jì)模式式可以幫幫助人們們簡(jiǎn)便地地復(fù)用以以前成功功的設(shè)計(jì)計(jì)方案,,提高工工作效率率7設(shè)計(jì)模式式:研究究現(xiàn)狀設(shè)計(jì)模式式的研究究現(xiàn)狀pattern與Java、C#pattern與組件件技術(shù)(如CORBA)pattern與系統(tǒng)統(tǒng)結(jié)構(gòu)pattern與泛型型編程(genericprogramming)相結(jié)合其他(例如UML等)8模式的分分類(lèi)(gof提出的23個(gè))9創(chuàng)建型結(jié)構(gòu)型行為型類(lèi)FactoryMethodAdapter(類(lèi))InterpreterTemplateMethod

對(duì)象AbstractFactoryBuilderPrototypeSingletonAdapter(對(duì)象)BridgeCompositeDecoratorFacadeFlyweightProxyChainofResponsibilityCommandIteratorMediatorMementoObserverStateStrategyVisitorBridge((橋梁)模式案例有一個(gè)叫叫做HuntBird的游戲,,里面需需要表示示各種各各樣的鳥(niǎo)鳥(niǎo)類(lèi)10Bridge((橋梁)模式最初的設(shè)設(shè)計(jì)11Bridge((橋梁)模式需求變化化:鳥(niǎo)類(lèi)類(lèi)要會(huì)飛飛12Bridge((橋梁)模式如果增加加一種鳥(niǎo)鳥(niǎo)類(lèi)“企企鵝”呢呢?13Bridge((橋梁)模式改進(jìn)方法法:對(duì)““飛”使使用多態(tài)態(tài)14Bridge((橋梁)模式改進(jìn)方法法:再次次使用繼繼承15Bridge((橋梁)模式如果增加加“游泳泳”行為為呢?16Bridge((橋梁)模式繼承只會(huì)會(huì)使得問(wèn)問(wèn)題越來(lái)來(lái)越復(fù)雜雜繼承是面面向?qū)ο笙蟮幕颈痉▽毎“???OO=類(lèi)+對(duì)象象+繼承承+消息息通信17設(shè)計(jì)原則1:組合優(yōu)先優(yōu)先使用組合,而不是繼承設(shè)計(jì)原則則:組合合優(yōu)先繼承復(fù)用用的優(yōu)點(diǎn)點(diǎn)可以很容容易的修修改或擴(kuò)擴(kuò)展父類(lèi)類(lèi)的實(shí)現(xiàn)現(xiàn)18設(shè)計(jì)原則則:組合合優(yōu)先繼承復(fù)用用的缺點(diǎn)點(diǎn)繼承破壞壞封裝,,因?yàn)楦父割?lèi)的實(shí)實(shí)現(xiàn)細(xì)節(jié)節(jié)完全暴暴露給子子類(lèi)(白盒復(fù)用用)父類(lèi)的實(shí)實(shí)現(xiàn)發(fā)生生改變,,則子類(lèi)類(lèi)必受牽牽連繼承是靜靜態(tài)的,,不能在在運(yùn)行時(shí)時(shí)發(fā)生改改變,不不靈活19設(shè)計(jì)原則則:組合合優(yōu)先組合復(fù)用用的優(yōu)點(diǎn)點(diǎn)不破壞封封裝,這這種復(fù)用用是黑盒盒復(fù)用,,因?yàn)槌沙蓡T對(duì)象象的內(nèi)部部細(xì)節(jié)對(duì)對(duì)新對(duì)象象保密所需依賴賴少(只依賴接接口)是動(dòng)態(tài)的的,可以以把成員員對(duì)象動(dòng)動(dòng)態(tài)替換換為另一一個(gè)類(lèi)型型相同的的對(duì)象組合復(fù)用用的缺點(diǎn)點(diǎn)對(duì)象數(shù)量量會(huì)增加加使用委托托(delegation)會(huì)使得系系統(tǒng)復(fù)雜雜20設(shè)計(jì)原則則:組合合優(yōu)先組合優(yōu)先先Favorcompositionoverinheritance當(dāng)需要應(yīng)應(yīng)對(duì)變化化的時(shí)候候,應(yīng)該該首先使使用組合合的方式式,而不不是繼承承因?yàn)榻M合合更加靈靈活例1:汽車(chē)有很很多種,,小轎車(chē)車(chē)、貨車(chē)車(chē)、客車(chē)車(chē),有的的車(chē)是客客貨兩用用,有的的車(chē)水陸陸兩用21設(shè)計(jì)原則則:組合合優(yōu)先如果使用用繼承來(lái)來(lái)描述::一旦增加加新的汽汽車(chē)種類(lèi)類(lèi)或用途途,都需需要大量量改動(dòng)原原有代碼碼22設(shè)計(jì)原則則:組合合優(yōu)先使用“組組合”思思路考慮慮問(wèn)題“汽車(chē)”擁?yè)碛心撤N種或某些些“用途途”“汽車(chē)””和“用用途”獨(dú)獨(dú)立變化化,互不不影響23設(shè)計(jì)原則則:組合合優(yōu)先區(qū)分“Is-A”與“Has--A”有一個(gè)系系統(tǒng)需要要描述經(jīng)經(jīng)理、雇雇員和學(xué)學(xué)生它們都是是人,所所以:24設(shè)計(jì)原則則:組合合優(yōu)先問(wèn)題有些人既既是經(jīng)理理,又是是學(xué)生,,比如某某位在讀讀MBA的老總25設(shè)計(jì)原則則:組合合優(yōu)先換一個(gè)角角度看問(wèn)問(wèn)題雇員、經(jīng)經(jīng)理、學(xué)學(xué)生其實(shí)實(shí)都是角角色的一一種人擁有角角色26Bridge((橋梁)模式是什么導(dǎo)導(dǎo)致設(shè)計(jì)計(jì)的不完完美?變化,無(wú)無(wú)法避免免的、經(jīng)經(jīng)常的需需求變化化設(shè)計(jì)者的的理想當(dāng)需求變變化的時(shí)時(shí)候,盡盡可能少少的修改改代碼就就可以滿滿足新的的需求27設(shè)計(jì)原則2:封裝可變性發(fā)現(xiàn)代碼容易變化的部分,封裝之,使它和不容易變化的部分獨(dú)立開(kāi)來(lái)Bridge((橋梁)模式“發(fā)現(xiàn)變變化點(diǎn)””28Bridge((橋梁)模式“封裝變變化點(diǎn)””變化點(diǎn)1:小鳥(niǎo)一一家29Bridge((橋梁)模式“封裝變變化點(diǎn)””變化點(diǎn)2:鳥(niǎo)類(lèi)的的行為——飛30Bridge((橋梁)模式“封裝變變化點(diǎn)””變化點(diǎn)2:鳥(niǎo)類(lèi)的的行為——游泳31Bridge((橋梁)模式“使變化化點(diǎn)和不不變點(diǎn)獨(dú)獨(dú)立開(kāi)來(lái)來(lái)”在這個(gè)例例子里其其實(shí)是兩兩個(gè)變化化點(diǎn)相獨(dú)獨(dú)立“鳥(niǎo)類(lèi)””和“行行為”什什么關(guān)系系?鳥(niǎo)類(lèi)擁有行為鳥(niǎo)類(lèi)行為為的具體體實(shí)現(xiàn),,委托““行為””類(lèi)來(lái)完完成32鳥(niǎo)兒擁有有飛、游游泳的行行為33Bridge((橋梁)模式使用橋梁梁模式的的效果比如增加加一種鳥(niǎo)鳥(niǎo)類(lèi)“鵝鵝”,相相應(yīng)的要要增加一種游泳泳的行為為“紅掌掌撥清波波”只需要增加一個(gè)鳥(niǎo)類(lèi)類(lèi)的子類(lèi)類(lèi)“鵝””增加一個(gè)游泳泳的行為為“紅掌掌撥清波波”設(shè)置“鵝鵝”的飛飛翔行為為為“飛飛不起來(lái)來(lái)”設(shè)置“鵝鵝”的游游泳行為為為“紅紅掌撥清清波”原有代碼碼不需要要改動(dòng)??!34Bridge((橋梁)模式35Bridge((橋梁)模式使用橋梁梁模式的的效果當(dāng)需求改改變的時(shí)時(shí)候(增增加動(dòng)物物或行為為),只只需要簡(jiǎn)簡(jiǎn)單添加加幾個(gè)類(lèi)類(lèi)對(duì)原有代代碼不需需要改動(dòng)動(dòng)保證了代代碼的穩(wěn)穩(wěn)定,提提高了可可維護(hù)性性36設(shè)計(jì)原則3:開(kāi)-閉原則在設(shè)計(jì)一個(gè)軟件的時(shí)候,應(yīng)當(dāng)使這個(gè)軟件可以在不被修改的前提下擴(kuò)展Bridge((橋梁)模式結(jié)構(gòu)37Bridge((橋梁)模式意圖將抽象部部分與它它的實(shí)現(xiàn)現(xiàn)部分分分離,使使它們都都可以獨(dú)獨(dú)立地變變化適用性抽象和它它的實(shí)現(xiàn)現(xiàn)部分可可以獨(dú)立立變化類(lèi)的抽象象以及它它的實(shí)現(xiàn)現(xiàn)都可以以通過(guò)生生成子類(lèi)類(lèi)的方法法加以擴(kuò)擴(kuò)充實(shí)現(xiàn)部分分的修改改不會(huì)對(duì)對(duì)客戶產(chǎn)產(chǎn)生影響響.......38Bridge((橋梁)模式應(yīng)用舉例例1:“小朋朋友畫(huà)畫(huà)畫(huà)”使用蠟筆筆需要大中中小三種種型號(hào)每種型號(hào)號(hào)各有12種顏色共36支39Bridge((橋梁)模式使用毛筆筆:大、中、、小3支毛筆12種顏料40Bridge((橋梁)模式蠟筆和毛毛筆的差差別蠟筆:筆筆和顏色色無(wú)法分分離,因因此需要要36種蠟筆毛筆:筆筆和顏色色可以獨(dú)獨(dú)立選擇擇,因此此只有3+12=15個(gè)子類(lèi)體現(xiàn)了Bridge模式將繼承關(guān)關(guān)系轉(zhuǎn)換換為組合合關(guān)系,,從而降降低了系系統(tǒng)間的的耦合,,減少了了代碼冗冗余41Bridge((橋梁)模式應(yīng)用舉例例2有一個(gè)CAD軟件,可可以畫(huà)多多種圖形形同時(shí)支持持多套繪繪圖算法法傳統(tǒng)的設(shè)設(shè)計(jì)42Bridge((橋梁)模式應(yīng)用Bridge模式43Bridge((橋梁)模式分析圖形Shape是一個(gè)抽抽象概念念,它可可以有許許多具體體化(變化點(diǎn)1)圖形的顯顯示Drawing是圖形的的實(shí)現(xiàn),,它也可可以有許許多套算算法(變化點(diǎn)2)Bridge模式使用用組合代代替繼承承,避免免了復(fù)雜雜的繼承承體系,,使得兩兩個(gè)變化化點(diǎn)獨(dú)立立變化,,互不影影響44設(shè)計(jì)原則則:開(kāi)-閉原則、、封裝可可變性“開(kāi)-閉”原則則BertrandMeyer:““Softwareshouldbeopenforextension,,butclosedformodification”在設(shè)計(jì)一一個(gè)軟件件的時(shí)候候,應(yīng)當(dāng)當(dāng)使這個(gè)個(gè)軟件可可以在不不被修改改的前提提下擴(kuò)展展解釋已有模塊塊,尤其其是最重重要的抽抽象層模模塊不能能動(dòng):保保證穩(wěn)定定性和延延續(xù)性可以擴(kuò)展展新模塊塊:增加加新行為為,保證證靈活性性45設(shè)計(jì)原則則:開(kāi)-閉原則、、封裝可可變性BertrandMeyer對(duì)象技術(shù)術(shù)大師法國(guó)工程程院院士士蘇黎世工工學(xué)院計(jì)計(jì)算機(jī)系系教授發(fā)明了Eiffel語(yǔ)言和按按契約設(shè)設(shè)計(jì)(DesignbyContract))的思想早年參與與了Z形式語(yǔ)言言的設(shè)計(jì)計(jì)名著《面向?qū)ο笙筌浖?gòu)構(gòu)造》46設(shè)計(jì)原則則:開(kāi)-閉原則、、封裝可可變性玉帝遵照照“開(kāi)-閉”原則則維護(hù)天天庭秩序序當(dāng)年孫悟悟空大鬧鬧天空,,向天庭庭發(fā)出挑挑戰(zhàn):““皇帝輪輪流做,,明年到到我家.......只教他搬搬出去,,將天宮宮讓與我我!”太白金星星給玉皇皇大帝建議道::“降一一道招安安圣旨,把把他宣來(lái)來(lái)上界...與他籍名名在箓...一則不動(dòng)動(dòng)眾勞師師,二則收仙仙有道也也?!?7設(shè)計(jì)原則則:開(kāi)-閉原則、、封裝可可變性分析“不動(dòng)眾眾勞師””、不破破壞天規(guī)規(guī)就是““閉”收仙有道道就是““開(kāi)”招安,就就是玉帝帝的“開(kāi)開(kāi)-閉”原則則:既讓讓孫悟空空滿意,,又不必必更改天天庭現(xiàn)有有的秩序序48設(shè)計(jì)原則則:開(kāi)-閉原則、、封裝可可變性分析現(xiàn)有的天天庭秩序序是系統(tǒng)統(tǒng)的最高高抽象層層弼馬溫這這個(gè)職位位只是具具體的實(shí)實(shí)現(xiàn)層招安的關(guān)關(guān)鍵就是是不允許許更改現(xiàn)現(xiàn)有的天天庭秩序序,但是是允許將將妖猴納納入到文文武百官官中,從從而擴(kuò)展展了這一一秩序的的具體實(shí)實(shí)現(xiàn)49設(shè)計(jì)原則則:開(kāi)-閉原則、、封裝可可變性“封裝可可變性原原則”gof:“考慮慮你的設(shè)設(shè)計(jì)中什什么可能能會(huì)發(fā)生生變化.......考慮你允允許什么么發(fā)生變變化而不不讓這一一變化導(dǎo)導(dǎo)致重新新設(shè)計(jì)””Shalloway:“發(fā)現(xiàn)現(xiàn)變化點(diǎn)點(diǎn),并封封裝之””一種可變變性不應(yīng)應(yīng)散落在在代碼的的很多角角落一種可變變性不應(yīng)應(yīng)當(dāng)與另另一種可可變性混混合在一一起50設(shè)計(jì)原則則:開(kāi)-閉原則、、封裝可可變性設(shè)計(jì)模式式對(duì)“開(kāi)開(kāi)-閉”原則則的支持持比如Bridge橋梁模式式:將抽抽象部分分和實(shí)現(xiàn)現(xiàn)部分分分別封裝裝,可以以分別獨(dú)獨(dú)立變化化51設(shè)計(jì)原則則:開(kāi)-閉原則、、封裝可可變性對(duì)“開(kāi)-閉”原則則支持的的不好的的例子java.util..Calendar52java提供的描描述歷法法的抽象象類(lèi)描述公歷歷的子類(lèi)我們希望望再派生生出一個(gè)個(gè)子類(lèi),,用于描描述陰歷歷設(shè)計(jì)原則則:開(kāi)-閉原則、、封裝可可變性問(wèn)題:Calendar只定義了了適用于于公歷的的常量和和方法53publicfinalstaticintSUNDAY==1;publicfinalstaticintMONDAY==2;...publicfinalstaticintJANUARY==0;;publicfinalstaticintFEBRUARY==1;;...publicvoidsetFistDayOfWeek(intvalue);;publicintgetFirstDayOfWeek());...設(shè)計(jì)原則則:開(kāi)-閉原則、、封裝可可變性問(wèn)題英文的星星期、月月份名稱(chēng)稱(chēng)不符合合中國(guó)陰陰歷的叫叫法陰歷以10天為一周周,公歷歷和陰歷歷每月的的天數(shù)也也不同,,所以Calendar關(guān)于星期期、月份份的算法法不適合合陰歷總之,Calendar無(wú)法容納納中國(guó)陰陰歷,因因此不支支持“開(kāi)開(kāi)-閉”原則則54Strategy(策略)模式橋梁模式式使得兩個(gè)個(gè)變化點(diǎn)點(diǎn)的獨(dú)立立55設(shè)計(jì)原則則找出應(yīng)用用中可能能需要變變化之處處把它們獨(dú)獨(dú)立出來(lái)來(lái)不要和那那些不需需要變化化的代碼碼混在一一起56Strategy(策略)模式單獨(dú)看飛飛的行為為的實(shí)現(xiàn)現(xiàn)策略模式式:封裝裝了一系系列算法法,使得得它們可可以相互互替換效果:算算法可以以獨(dú)立變變化57設(shè)計(jì)原則則針對(duì)接口口編程,,而不是是針對(duì)實(shí)實(shí)現(xiàn)編程程58策略模式式-開(kāi)閉原則則.例-計(jì)算價(jià)格格PublicclassPart{privatedoublebasePrice;;publicvoidsetPrice(doubleprice)){basePrice==price;}publicdoublegetPrice(){{returnbasePrice;}}59某類(lèi)方法Publicdoubletotalprice((Part[]]parts){doubletotal==0.0;for((inti=0;;i<parts.length;;i+++){total++=parts[i].getPrice());}returntotal;;}60思考內(nèi)存折扣扣?61方法Publicdoubletotalprice((Part[]]parts){doubletotal==0.0;for((inti=0;;i<parts.length;;i+++){if(parts[I]instanceofMemory)total++=parts[i].getPrice())*0.9;elsetotal++=parts[i].getPrice());}returntotal;;}62思考符合OCP嗎?63方法?PublicclassMemoryextendsPart{publicdoublegetPrice(){{returnbasePrice*0.9;}}64更好的方方法?采用一個(gè)個(gè)PricePolicy類(lèi),通過(guò)過(guò)對(duì)其進(jìn)進(jìn)行繼承承以提供供不同的的計(jì)價(jià)策策略65方法PublicclassPart{privatePricePolicypricePolicy;publicvoidsetPricePolicy(PricePolicypolicy)){pricePolicy==policy;}publicvoidsetPrice(doubleprice)){pricePolicy.setPrice(price));}publicdoublegetPrice(){{returnpricePolicy..getPrice(();}}66價(jià)格策略略PublicclassPricePolicy{{privatedoublebasePrice;;publicvoidsetPrice(doubleprice)){basePrice==price;}publicdoublegetPrice(){{returnbasePrice;}}67銷(xiāo)售策略略PublicclassSaleextendsPricePolicy{privatedoublediscount;publicvoidsetDiscount(doublediscount)){this.discount=discount;;}publicdoublegetPrice(){{returnbasePrice*discount;;}}68Strategy(策略):定義所所有支持持的算法法的公共共接口ConcreteStrategy(具體策略略):實(shí)現(xiàn)具具體算法法Context(上下文):用一個(gè)ConcreteStrategy對(duì)象來(lái)配配置維護(hù)一個(gè)個(gè)對(duì)Strategy對(duì)象的引引用可定義一一個(gè)接口口來(lái)讓Strategy訪問(wèn)它的的數(shù)據(jù)69階段小結(jié)結(jié)設(shè)計(jì)原則則70限制變化化的影響響范圍增加新功功能,要要做到只只增加新新代碼,,而不改改動(dòng)老代代碼盡量用組組合,而而不是繼繼承組合優(yōu)先先開(kāi)-閉原則封裝可變變性階段小結(jié)結(jié)策略模式式使得算法法可以獨(dú)獨(dú)立變化化使用組合合取代繼繼承,封封裝了可可變性,,保證了了“開(kāi)-閉”橋梁模式式使得抽象象和實(shí)現(xiàn)現(xiàn)獨(dú)立變變化避免了兩兩個(gè)變化化點(diǎn)的耦耦合71Adapter(適配器)模式例子1:“不合合適的插插座”你的電腦腦的插頭頭是三相相的而墻上的的插座只只有兩相相的插頭和插插座的““接口””不匹配配,怎么么辦?72Adapter(適配器)模式例子2:HuntBird游戲中,,希望增增加一種種鳥(niǎo)類(lèi)““鴨子””但是發(fā)現(xiàn)現(xiàn)以前有有一個(gè)系系統(tǒng)中已已經(jīng)有了了“鴨子子”類(lèi),,希望重重用老代代碼73Adapter(適配器)模式新老代碼碼接口不不一致74Adapter(適配器)模式疑問(wèn)把老代碼碼修改一一下不就就可以了了么?如如下:75Adapter(適配器)模式否定首先,老老代碼不不一定允允許修改改比如可能能根本沒(méi)沒(méi)有代碼碼,只有有鏈接庫(kù)庫(kù)其次,修修改代碼碼工作量量可能很很大容易出錯(cuò)錯(cuò)還記得““開(kāi)-閉原則””么76Adapter(適配器)模式應(yīng)用(對(duì)象)適配器模模式實(shí)現(xiàn)現(xiàn)接口轉(zhuǎn)轉(zhuǎn)換77Adapter(適配器)模式理解1:接口轉(zhuǎn)轉(zhuǎn)換78客戶(鳥(niǎo))被適配者(鴨子)適配器請(qǐng)求轉(zhuǎn)換后的請(qǐng)求Adapter(適配器)模式79叫呷呷叫Adapter(適配器)模式理解2:重新包包裝,改改變接口口80Adapter(適配器)模式類(lèi)適配器器81Adapter(適配器)模式結(jié)構(gòu)對(duì)象Adapter82Adapter(適配器)模式結(jié)構(gòu)類(lèi)Adapter83Adapter(適配器)模式意圖將一個(gè)類(lèi)類(lèi)的接口口轉(zhuǎn)換成成客戶希希望的另另外一個(gè)個(gè)接口Adapter模式使得得原本由由于接口口不兼容容而不能能一起工工作的那那些類(lèi)可可以一起起工作84Adapter(適配器)模式應(yīng)用舉例例1我們打算算編寫(xiě)一一個(gè)畫(huà)圖圖軟件其中畫(huà)圓圓形已經(jīng)經(jīng)有了一一個(gè)現(xiàn)成成的類(lèi)但是接口口不同,,不能直直接使用用85Adapter(適配器)模式使用對(duì)象象Adapter86Adapter(適配器)模式應(yīng)用舉例例2缺省適配配模式——“魯達(dá)剃度度”凡是和尚尚都應(yīng)該該如此::87Adapter(適配器)模式但是魯智智深并不不是這樣樣88魯智深::習(xí)武(){拳打鎮(zhèn)關(guān)關(guān)西();大鬧五臺(tái)臺(tái)山();倒拔垂楊楊柳();火燒瓦官官寺();}Adapter(適配器)模式所以當(dāng)初初魯達(dá)剃剃度時(shí),,眾僧說(shuō)說(shuō):“這個(gè)人人形容丑丑惡,相相貌兇頑頑,不可可剃度””89?Adapter(適配器)模式但是長(zhǎng)老老卻說(shuō)::“此人上上應(yīng)天星星,心地地剛直。。雖然時(shí)時(shí)下兇頑頑,命中中駁雜,,久后卻卻得清靜靜。證過(guò)過(guò)非凡,,汝等皆皆不及他他”90Adapter(適配器)模式“天星””就是缺缺省適配配器當(dāng)你不想想/不能實(shí)現(xiàn)現(xiàn)接口的的所有方方法時(shí)利用缺省省適配器器類(lèi),提提供這些些方法的的缺省實(shí)實(shí)現(xiàn)從這個(gè)類(lèi)類(lèi)再派生生出的子子類(lèi)就可可以不去去實(shí)現(xiàn)那那些不想想實(shí)現(xiàn)的的方法了了91真實(shí)世界界中的適適配器想一想Java語(yǔ)言中不不同版本本中有沒(méi)沒(méi)有需要要進(jìn)行適適配的92真實(shí)世界界中的適適配器早期java版本中集集合(Collection)類(lèi)型((例如::Vector,,Stack,,Hashtable)都實(shí)現(xiàn)了了一個(gè)elements())方法。該該方法返返回一個(gè)個(gè)Enumeration(枚舉))新版本中中開(kāi)始使使用Iterator(迭代器器)接口口,這個(gè)個(gè)接口和和枚舉接接口很像像,但不不同的是是,迭代代器還提提供了刪刪除元素素的能力力。93問(wèn)題面對(duì)遺留留代碼,,這些代代碼會(huì)暴暴露出枚枚舉器接接口,但但我們又又希望在在新的代代碼中只只使用迭迭代器。。解決辦法法構(gòu)造一個(gè)個(gè)適配器器將枚舉適適配到迭迭代器949596publicclassEnumerationIteratorimplementsIterator{///適配器看看起來(lái)就就是一個(gè)個(gè)Iterator///我們使用用組合的的方式,將枚舉結(jié)結(jié)合進(jìn)適適配器中中,用實(shí)例變變量記錄錄Enumerationenumeration;publicEnumerationIterator(Enumerationenumeration){{this.enumeration=enumeration;;} ///迭代器的的hasNext其實(shí)是委委托給enumeration的hasMoreElements方法publicbooleanhasNext(){{returnenumeration..hasMoreElements();;} ///迭代器的的next其實(shí)是委委托給enumeration的nextElement方法publicObjectnext((){{returnenumeration..nextElement((); }//很不幸,我們不能能支持迭迭代器的的remove方法,所以必須須放棄,這里是拋拋出一個(gè)個(gè)異常publicvoidremove((){{thrownewUnsupportedOperationException((); }}97實(shí)例有一個(gè)類(lèi)類(lèi)(adaptee)實(shí)現(xiàn)了數(shù)數(shù)學(xué)中的的冪次運(yùn)運(yùn)算,方方法中需需要傳入入兩個(gè)參參數(shù),一一個(gè)是基基數(shù)base,另外一一個(gè)是冪冪次exp。現(xiàn)在客客戶端需需要一個(gè)個(gè)求得一一個(gè)數(shù)的的平方的的函數(shù)接接口(target),傳入一一個(gè)數(shù),,得到它它的平方方值。為為了復(fù)用用已經(jīng)存存在的類(lèi)類(lèi)adaptee,使用Adapter來(lái)適配adaptee,adapter實(shí)現(xiàn)了target接口。9899在架構(gòu)層層次上的的應(yīng)用JDBC驅(qū)動(dòng)軟件件與適配配器模式式JDBC給出一個(gè)個(gè)客戶端端通用的的界面。。每個(gè)數(shù)數(shù)據(jù)庫(kù)引引擎的JDBC驅(qū)動(dòng)軟件件都是一一個(gè)介于于JDBC接口和數(shù)數(shù)據(jù)庫(kù)引引擎接口口之間的的適配器器軟件抽象的JDBC接口和各各個(gè)數(shù)據(jù)據(jù)庫(kù)引擎擎的API之間都需需要相應(yīng)應(yīng)的適配配器軟件件,即為為各個(gè)數(shù)數(shù)據(jù)庫(kù)引引擎準(zhǔn)備備的驅(qū)動(dòng)動(dòng)軟件。。100JDBC/ODBC橋梁如果沒(méi)有有合適的的JDBC驅(qū)動(dòng)軟件件,用戶戶也可以以通過(guò)ODBC驅(qū)動(dòng)軟件件把JDBC通過(guò)一個(gè)個(gè)JDBC/ODBC橋梁軟件件與ODBC驅(qū)動(dòng)軟件件連接起起來(lái),從從而達(dá)到到連接數(shù)數(shù)據(jù)庫(kù)的的目的。。101設(shè)計(jì)原則則:里氏氏代換原原則例子1:“圓是是不是橢橢圓?””在幾何學(xué)學(xué)里,圓圓是橢圓圓的一種種特殊情情況因此,把把橢圓看看作父類(lèi)類(lèi),把圓圓作為子子類(lèi)102設(shè)計(jì)原則則:里氏氏代換原原則問(wèn)題橢圓有長(zhǎng)長(zhǎng)軸、短短軸圓會(huì)完全全繼承下下來(lái)這些對(duì)于于圓來(lái)說(shuō)說(shuō)毫無(wú)意意義類(lèi)似的::“正方方形不是是矩形””103Circlecircle;circle..GetMajorAxis();;設(shè)計(jì)原則則:里氏氏代換原原則例子2:“企鵝鵝不是鳥(niǎo)鳥(niǎo)的子類(lèi)類(lèi)”凡是鳥(niǎo)都都會(huì)飛但是企鵝鵝不會(huì)104設(shè)計(jì)原則則:里氏氏代換原原則例子3我們需要要設(shè)計(jì)一一個(gè)類(lèi)FileName來(lái)描述文文件名,,而文件件名不就就是一個(gè)個(gè)特殊的的字符串串么?所所以我們們?nèi)绱嗽O(shè)設(shè)計(jì):105設(shè)計(jì)原則則:里氏氏代換原原則問(wèn)題凡是字符符串都支支持相加加操作,,也就是是說(shuō)兩個(gè)個(gè)字符串串相加,,結(jié)果還還是一個(gè)個(gè)字符串串可是兩個(gè)個(gè)文件名名相加,,還是一一個(gè)合法法的文件件名么??比如:““c:\a.txt”++““d:\\b.txt””結(jié)果是::“c:\a.txtd::\b..txt”106設(shè)計(jì)原則則:里氏氏代換原原則錯(cuò)在哪里里?墨子論““取譬””“白馬,,馬也;;乘白馬馬,乘馬馬也。驪驪馬,馬馬也;乘乘驪馬,,乘馬也也?!苯忉?zhuān)喊装遵R、驪驪馬(黑馬)都是馬,,既然馬馬可以騎騎,那么么白馬和和驪馬肯肯定也可可以騎107設(shè)計(jì)原則則:里氏氏代換原原則LiskovSubstitutionPrinciple一個(gè)軟件件如果使使用的是是一個(gè)父父類(lèi)的話話,如果果把該父父類(lèi)換成成子類(lèi),,它不能能察覺(jué)出出父類(lèi)對(duì)對(duì)象和子子類(lèi)對(duì)象象的區(qū)別別也就是凡凡是父類(lèi)類(lèi)適用的的地方子子類(lèi)也適適用繼承只有有滿足里里氏代換換原則才才是合理理的108設(shè)計(jì)原則4:里氏代換原則凡是父類(lèi)適用的地方子類(lèi)應(yīng)當(dāng)也適用設(shè)計(jì)原則則:里氏氏代換原原則反過(guò)來(lái)的的代換不不成立子類(lèi)適用用的地方方不要求求父類(lèi)一一定能適適用墨子又說(shuō)說(shuō)“娣,美美人也,,愛(ài)娣,,非愛(ài)美美人也.......盜,人也也,惡盜盜,非惡惡人也””妹妹是美美女,哥哥哥喜歡歡妹妹,,并不是是因?yàn)橄蚕矚g美女女小偷是人人,討厭厭小偷,,并不討討厭所有有人109設(shè)計(jì)原則則:里氏氏代換原原則Java語(yǔ)言對(duì)此此類(lèi)問(wèn)題題的防范范它的String類(lèi)是final的,不能能繼承正確的方方法使用Adapter模式110設(shè)計(jì)原則則:里氏氏代換原原則Java中的反例例它的Stack類(lèi)是從Vector類(lèi)繼承下下來(lái)的“棧不就就是施加加了訪問(wèn)問(wèn)限制的的數(shù)組么么?”所以“StackIs-AVector”111設(shè)計(jì)原則則:里氏氏代換原原則用里氏代代換原則則來(lái)判斷斷凡是數(shù)組組行得通通的地方方,換成成棧也行行得通么么?Vector可以隨機(jī)機(jī)訪問(wèn),,可以任任意修改改里面的的元素...這些都是是Stack所不允許許的因此Stack不能從Vector繼承下來(lái)來(lái),它不不能擁有有Vector的接口112設(shè)計(jì)原則則:里氏氏代換原原則看看C++STL是怎么辦辦的STL中的stack其實(shí)是一一個(gè)Adapter113template<classT,classCont=deque<<T>>>classstack{{public:voidpush(constvalue__type&x){c..push_back(x));}}voidpop(){{c..pop_back((x);;}protected:Contc;;};設(shè)計(jì)模式式-工廠廠模式當(dāng)看到““new””,就會(huì)想想到“具具體”115116一個(gè)計(jì)算算器例子子publicclassOperation{privatedoublenumberA=0;;privatedoublenumberB=0;;publicvirtualdoubleGetResult(){{doubleresult=0;;returnresult; }}classOperationAdd::Operation{{publicoverridedoubleGetResult()){doubleresult=0;;result==numberA++numberB;returnresult;}當(dāng)遇到一一群相關(guān)關(guān)的具體體類(lèi)時(shí),,通常見(jiàn)見(jiàn)到下面面的代碼碼OperationcreateOperation(Stringoperate){Operationoper;switch((operate){{case”+””:oper=newOperationAdd());break;case”=””:oper=newOperationSub());break;case”*””:oper=newOperationMul());break;……...}}117如果計(jì)算算器要增增加更多多的運(yùn)算算類(lèi)型怎怎么辦?118簡(jiǎn)單工廠廠開(kāi)始封裝裝創(chuàng)建對(duì)對(duì)象的代代碼建立一個(gè)個(gè)簡(jiǎn)單工工廠當(dāng)需要Operation時(shí),就叫叫工廠做做一個(gè)119定義簡(jiǎn)單單工廠120PublicclassOperationFactory{publicstaticOperationcreateOperate(Stringoperate){{Operationoper=null;switch((operate){{case”+””:oper=newOperationAdd());break;case”=””:oper=newOperationSub());break;case”*””:oper=newOperationMul());break;case”/””:oper=newOperationDiv());break;}returnoper;;}}121簡(jiǎn)單工廠廠實(shí)現(xiàn)客戶端的的實(shí)現(xiàn)Operationoper;oper=OperationFactory.createOperate(“++”);;oper.NumberA==1;oper.NumberB==2;doubleresult=oper.GetResult(();122簡(jiǎn)單工廠廠模式的的優(yōu)點(diǎn)123簡(jiǎn)單工廠廠類(lèi)中包包含了必必要的邏邏輯判斷斷,根據(jù)據(jù)客戶端端的選擇擇條件動(dòng)動(dòng)態(tài)實(shí)例例化相關(guān)關(guān)的類(lèi),,對(duì)于客戶戶端來(lái)說(shuō)說(shuō),去除除了與具具體產(chǎn)品品的依賴賴。就像計(jì)算算器,讓讓客戶端端不用管管該用哪哪個(gè)類(lèi)的的實(shí)例,,只要把把‘+’給工廠廠,工廠廠自動(dòng)就就給出了了實(shí)例,,客戶端端只要去去做運(yùn)算算就可以以了,不不同的實(shí)實(shí)例會(huì)實(shí)實(shí)現(xiàn)不同同的運(yùn)算算。簡(jiǎn)單工廠廠實(shí)現(xiàn)了了責(zé)任的的分割。。問(wèn)題如果要加加一個(gè)““求M數(shù)的N此方”的的功能,,就要在在原有方方法中加加一個(gè)分分支條件件,就要要修改原原有的類(lèi)類(lèi),違背背了開(kāi)放-封閉原則,于于是工廠廠方法就就來(lái)了。。124定義工廠廠方法模模式工廠方法法模式定定義了一一個(gè)創(chuàng)建建對(duì)象的的接口由子類(lèi)決決定實(shí)例例化的類(lèi)類(lèi)是哪一一個(gè)工廠方法法使一個(gè)個(gè)類(lèi)的實(shí)實(shí)例化延延遲到其其子類(lèi)。。125遵循倒置置依賴原原則的指指導(dǎo)方針針變量不可可以持有有具體類(lèi)類(lèi)的引用用如果使用用new,就會(huì)持持有具體體類(lèi)的引引用可以改用用工廠來(lái)來(lái)避開(kāi)這這樣的做做法不要讓類(lèi)類(lèi)派生自自具體類(lèi)類(lèi)如果派生生自具體體類(lèi),就就會(huì)依賴賴具體類(lèi)類(lèi)請(qǐng)派生自自一個(gè)抽抽象(接接口或抽抽象類(lèi)))不是隨時(shí)時(shí)都要遵遵循這個(gè)個(gè)原則如直接實(shí)實(shí)例化字字符串對(duì)對(duì)象126應(yīng)用依賴賴倒置原原則要依賴抽抽象,不不要依賴賴具體類(lèi)類(lèi)我們把工工廠類(lèi)抽抽象出一一個(gè)接口口,這個(gè)個(gè)接口只只有一個(gè)個(gè)方法,,就是創(chuàng)創(chuàng)建抽象象產(chǎn)品的的工廠方方法。然后,所所有的要要生產(chǎn)具具體類(lèi)的的工廠,,就去實(shí)實(shí)現(xiàn)這個(gè)個(gè)接口。。這樣,一一個(gè)簡(jiǎn)單單工廠模模式的工工廠類(lèi),,就變成成了一個(gè)個(gè)工廠抽抽象接口口和多個(gè)個(gè)具體生生產(chǎn)對(duì)象象的工廠廠。于是,我我們要增增加‘求求M數(shù)的N次方’的的功能時(shí)時(shí),就不不需要更更改原有有的工廠廠類(lèi)了,,只需要要增加此此功能的的運(yùn)算類(lèi)類(lèi)和相應(yīng)應(yīng)的工廠廠類(lèi)就可可以了。。127工廠方法法模式實(shí)實(shí)現(xiàn)128工廠方法法模式實(shí)實(shí)現(xiàn)先構(gòu)建一一個(gè)工廠廠接口InterfaceIFactory{OperationCreateOperation();;}129然后加減減乘除各各建一個(gè)個(gè)具體工工廠去實(shí)實(shí)現(xiàn)這個(gè)個(gè)接口classAddFactory:IFactory{publicOperationCreateOperation()){returnnewOperationAdd());}}classSubFactory:IFactory{publicOperationCreateOperation()){returnnewOperationSub());}}130工廠方法法模式實(shí)實(shí)現(xiàn)然后加減減乘除各各建一個(gè)個(gè)具體工工廠去實(shí)實(shí)現(xiàn)這個(gè)個(gè)接口classMulFactory:IFactory{publicOperationCreateOperation()){returnnewOperationMul());}}classDivFactory:IFactory{publicOperationCreateOperation()){returnnewOperationDiv());}}131工廠方法法模式實(shí)實(shí)現(xiàn)客戶端的的實(shí)現(xiàn)IFactoryoperFactory==newAddFactory();;Operationoper==operFactory.CreateOperation());oper.NumberA==1;oper.NumberB==2;doubleresult=oper.GetResult(();132工廠方法法模式實(shí)實(shí)現(xiàn)工廠方法法模式實(shí)實(shí)現(xiàn)時(shí),,客戶端需需要決定定實(shí)例化化哪一個(gè)個(gè)工廠來(lái)來(lái)實(shí)現(xiàn)運(yùn)運(yùn)算類(lèi),選擇判判斷的問(wèn)問(wèn)題還是是存在的的,也就就是說(shuō),,工廠方方法把簡(jiǎn)簡(jiǎn)單工廠廠的內(nèi)部部邏輯判判斷轉(zhuǎn)移移到了客客戶端代代碼來(lái)進(jìn)進(jìn)行。如果要加加功能,,本來(lái)是是改工廠廠類(lèi)的,,而現(xiàn)在在是修改改客戶端端。133工廠方法法模式一個(gè)抽象象產(chǎn)品類(lèi)類(lèi),可以以派生出出多個(gè)具具體產(chǎn)品品類(lèi)。一一個(gè)抽抽象工廠廠類(lèi),可可以派生生出多個(gè)個(gè)具體工工廠類(lèi)。。每個(gè)具體體工廠類(lèi)類(lèi)只能創(chuàng)創(chuàng)建一個(gè)個(gè)具體產(chǎn)產(chǎn)品類(lèi)的的實(shí)例。。134工廠方法法模式雷鋒工廠廠雷鋒是眾眾人皆知知的做好好人好事事的模范范。作為一名名大學(xué)生生,每個(gè)個(gè)人都可可以以雷雷鋒做好好事的名名義去幫幫助老人人。在這里,,’雷鋒’類(lèi),擁有有掃地、、洗衣、、買(mǎi)米等等方法。?!畬W(xué)雷鋒鋒的大學(xué)學(xué)生’類(lèi)類(lèi)是‘雷雷鋒’類(lèi)類(lèi)的一個(gè)個(gè)繼承。。而大學(xué)生生是要畢畢業(yè)的,,幫助老老人是長(zhǎng)長(zhǎng)期的,,所以‘‘社區(qū)志志愿者’’更適合合。于是,增增加一個(gè)個(gè)繼承‘‘雷鋒’’類(lèi)的‘‘社區(qū)志志愿者’’類(lèi)。135雷鋒類(lèi)classLeiFeng{publicvoidSweep()){Console.WriteLine(““掃地”); }publicvoidWash(){{Console.WriteLine(““洗衣”); }publicvoidBuyRice(){{Console.WriteLine(““買(mǎi)米”); }}136大學(xué)生類(lèi)類(lèi)及社區(qū)區(qū)志愿者者classUndergraduate:LeiFeng{}}classVolunteer::LeiFeng{}}137簡(jiǎn)單工廠廠模式ClassSimpleFactory{publicstaticLeiFengCreateLeiFeng(stringtyple)){LeiFengresult==null;;switch((type)){case”學(xué)雷鋒的的大學(xué)生生”:result==newUndergradute();;break;;case”社區(qū)志愿愿者”:result==newVolunteer());break;}returnresult;}}138客戶端的的實(shí)現(xiàn)LeiFengstudentA=SimpleFacatory.CreateLeiFeng(“學(xué)雷鋒的的大學(xué)生生”);studentA.BuyRice();;LeiFengstudentB=SimpleFacatory.CreateLeiFeng(“學(xué)雷鋒的的大學(xué)生生”);studentB.Sweep());LeiFengstudentC=SimpleFacatory.CreateLeiFeng(“學(xué)雷鋒的的大學(xué)生生”);studentC.Wash();;139簡(jiǎn)單工廠廠模式在這里,,需要再再任何實(shí)實(shí)例化的的時(shí)候?qū)憣?xiě)出這個(gè)個(gè)工廠的的代碼。。這里有有重復(fù),,于是用用工廠方方法模式式來(lái)寫(xiě)。。140工廠方法法模式InterfaceIFactory{LeiFengCreateLeiFeng(();}classUndergraduteFactory:IFactory{publicLeiFengCreateLeiFeng(){returnnewUndergraduate();;}}141classVolunteerFactory:IFactory{publicLeiFengCreateLeiFeng(){returnnewVolunteer(();}}}客戶端代代碼Ifactoryfactory==newUndergraduateFactory());LeiFengstudentA=factory.CreateLeiFeng();;LeiFengstudentB=factory.CreateLeiFeng();;LeiFengstudentC=factory.CreateLeiFeng();;studentA.BuyRice();;studentB.Sweep());studentC.Wash();;142工廠方法法模式在這里,,盡管如如果要換換成‘社社區(qū)志愿愿者’也也還是要要修改代代碼,但但只用修修改一處處就可以以。工廠方法法克服了了簡(jiǎn)單工工廠違背背開(kāi)放-封閉原則則的缺點(diǎn)點(diǎn),又保保持了封封裝對(duì)象象創(chuàng)建過(guò)過(guò)程的優(yōu)優(yōu)點(diǎn)。它們都是是集中封封裝了對(duì)對(duì)象的創(chuàng)創(chuàng)建,使使得要更更換對(duì)象象時(shí),不不需要做做大的改改動(dòng)就可可實(shí)現(xiàn),,降低了了客戶程程序與產(chǎn)產(chǎn)品對(duì)象象的耦合合。143工廠方法法模式工廠方法法模式是是簡(jiǎn)單工工廠模式式的進(jìn)一一步抽象象和推廣廣,由于于使用了了多態(tài)性性,工廠廠方法模模式保持持了簡(jiǎn)單單工廠模模式的優(yōu)優(yōu)點(diǎn),而而且克服服了它的的缺點(diǎn)。。但缺點(diǎn)是是由于每每加一個(gè)個(gè)產(chǎn)品,,就需要要加一個(gè)個(gè)產(chǎn)品工工廠的類(lèi)類(lèi),增加加了額外外了開(kāi)發(fā)發(fā)量。144工廠方法法模式抽象工廠廠模式提供一個(gè)個(gè)創(chuàng)建一系列相相關(guān)或相相互依賴賴對(duì)象的的接口,而無(wú)需需指定它它們具體體的類(lèi)。。145定義抽象象工廠模模式146數(shù)據(jù)訪問(wèn)問(wèn)程序用戶類(lèi)User,假設(shè)只只有ID和Name兩個(gè)字段段。SqlserverUser類(lèi)和AccessUser類(lèi),用于于操作User表,假設(shè)設(shè)只有““新增用用戶”和和“得到到用戶””方法。。SqlserverUser類(lèi),用于于訪問(wèn)SQLServer的用戶。。AccessUser類(lèi),用于于訪問(wèn)Access的用戶。。147用工廠方方法模式式的數(shù)據(jù)據(jù)訪問(wèn)程程序148InterfaceIUser{voidInsert(Useruser);UserGetUser((intid);;}classSqlserverUser:IUser{publicvoidInsert((Useruser){Console.WriteLine(““在SQLServer中給User表增加一一條記錄錄”);}publicvoidGetUser(intid)){Console.WriteLine(““在SQLServer中根據(jù)ID得到User表的一條條記錄”);returnnull;}}149用工廠方方法模式式的數(shù)據(jù)據(jù)訪問(wèn)程程序classAccessUser:IUser{publicvoidInsert((Useruser){Console.WriteLine(““在Access中給User表增加一一條記錄錄”);}publicvoidGetUser(intid)){Console.WriteLine(““在Access中根據(jù)ID得到User表的一條條記錄”);returnnull;}}150工廠方法法IFactory接口:定義一個(gè)個(gè)創(chuàng)建訪訪問(wèn)User表對(duì)象的的抽象的的工廠接接口。InterfaceIFactory{IuserCreateUser();;}151SqlServerFactory類(lèi),AccessFactory類(lèi)實(shí)現(xiàn)接接口classSqlServerFactory:IFactory{publicIuserCreateUser()){returnnewSqlserverUser();;}}classAccessFactory:IFactory{publicIuserCreateUser()){returnnewAccessUser();;}}152客戶端實(shí)實(shí)現(xiàn)StaticvoidMain(string[]]args)){Useruser==newUser());Ifactoryfactory=newSqlServerFactory(();Iuseriu==factory..CreateUser());iu.Insert((user);;iu.GetUser(1));Console.Read(();}153用抽象工工廠模式式的數(shù)據(jù)據(jù)訪問(wèn)程程序154Idepartment接口,用用于客戶戶端訪問(wèn)問(wèn),解除除與具體體數(shù)據(jù)庫(kù)庫(kù)訪問(wèn)的的耦合。。interfaceIDepartment{{voidInsert(Departmentdepartment));DepartmentGetDepartment(intid));}SqlserverDepartment類(lèi),AccessDepartment類(lèi)分別用用于訪問(wèn)問(wèn)SQLSever、Access的Department。155classSqlserverDepartment:IDepartment{publicvoidInsert((Departmentdepartment){{Console.WriteLine(““在SQLServer中的Department表增加一條條記錄”);}publicDepartmentGetDepartment(intid)){Console.WriteLine(““在SQLServer中根據(jù)ID得到Department表中的一一條記錄錄”);returnnull;}}156classAccessDepartment:IDepartment{publicvoidInsert((Departmentdepartment){{Console.WriteLine(““在Access中的Department表增加一條記錄錄”);}publicDepartmentGetDepartment(intid)){Console.WriteLine(““在Access中根據(jù)ID得到Department表中的一一條記錄錄”);returnnull;}}157interfaceIFactory{IuserCreateUser();;IDepartmentCreateDepartment();;}classSqlServerFactory:IFactory{publicIuserCreateUser()){returnnewSqlserverUser();;}publicIDepartmentCreateDepartment()){returnnewSqlServerDepartment();;}}158classAccessFactory:IFactory{publicIuserCreateUser()){returnnewAccessUser();;}publicIDepartmentCreateDepartment()){returnnewAccessDepartment();;}}159客戶端實(shí)實(shí)現(xiàn):StaticvoidMain(string[]]args)){Useruser==newUser());Departmentdept==newDepartment());IFactoryfactory=newAccessFactory(();IUseriu==factory..CreateUser());iu.Insert((user);;iu.GetUser(1));Idepartmentid==factory..CreateDepartment());id.Insert((dept);;id.GetDepartment(1));Console.Read(();}160抽象工廠廠模式的的優(yōu)點(diǎn)易于交換換產(chǎn)品系系列,由由于具體體工廠類(lèi)類(lèi)在一個(gè)個(gè)應(yīng)用中中只需要要在初始始化時(shí)出出現(xiàn)一次次,這就就使得改改變一個(gè)個(gè)應(yīng)用的的具體工工廠變得得非常容容易,它它只需要要改變具具體工廠廠即可使使用不同同的產(chǎn)品品配置。。它讓具體體的創(chuàng)建建實(shí)例過(guò)過(guò)程與客客戶端分分離,客客戶端是是通過(guò)它它們的抽抽象接口口操縱實(shí)實(shí)例,產(chǎn)產(chǎn)品的具具體類(lèi)名名也被具具體工廠廠的實(shí)現(xiàn)現(xiàn)分離,,不會(huì)出出現(xiàn)在客客戶代碼碼中。161抽象工廠廠模式多個(gè)抽象象產(chǎn)品類(lèi)類(lèi),每個(gè)個(gè)抽象產(chǎn)產(chǎn)品類(lèi)可可以派生生出多個(gè)個(gè)具體產(chǎn)產(chǎn)品類(lèi)。。一一個(gè)個(gè)抽象工工廠類(lèi),,可以派派生出多多個(gè)具體體工廠類(lèi)類(lèi)。每每個(gè)具體體工廠類(lèi)類(lèi)可以創(chuàng)創(chuàng)建多個(gè)個(gè)具體產(chǎn)產(chǎn)品類(lèi)的的實(shí)例。。162比較工廠廠方法和和抽象方方法抽象工廠廠的需求求:創(chuàng)建建一個(gè)產(chǎn)產(chǎn)品家族族負(fù)責(zé)在抽抽象工廠廠中創(chuàng)建建產(chǎn)品的的方法,,通常是是以“工工廠方法法”來(lái)實(shí)實(shí)現(xiàn)的163FactoryMethod(工廠方法法)模式例子:““去快餐餐廳吃飯飯”164165voidBuyFood(string餐館,string食品){if(餐館==""KFC"){{if(食品==""Chicken"))hamburger==newKFCChickenHamburger;elseif(food===""Fish"))hamburger==newKFCFishHamburger;}elseif(restaurant===""McDonald""){{if(food===""Chicken"))hamburger==newMcDonaldChickenHamburger;;elseif(food===""Fish"))hamburger==newMcDonaldFishHamburger;;}}FactoryMethod(工廠方法法)模式增加一種種新的食食物呢??166FactoryMethod(工廠方法法)模式傳統(tǒng)設(shè)計(jì)計(jì)的缺點(diǎn)點(diǎn)依賴具體體167voidBuyFood(string餐館,string食品){if(餐館==""KFC"){{if(食品==""Chicken"))hamburger==newKFCChickenHamburger;elseif(food===""Fish"))hamburger==newKFCFishHamburger;}...FactoryMethod(工廠方法法)模式“Abstractionshouldnotdependupondetails..Detailsshoulddependuponabstractions”168設(shè)計(jì)原則5:依賴倒置原則抽象不應(yīng)當(dāng)依賴于細(xì)節(jié)細(xì)節(jié)應(yīng)當(dāng)依賴于抽象設(shè)計(jì)原則則:依賴賴倒置原原則為什么說(shuō)說(shuō)“倒置置”傳統(tǒng)的設(shè)設(shè)計(jì)是抽抽象層依依賴具體體層傳統(tǒng)的重重用,側(cè)側(cè)重于具具體層次次的模塊塊,比如如算法、、數(shù)據(jù)結(jié)結(jié)構(gòu)、函函數(shù)庫(kù)因此軟件件的高層層模塊依依賴低層層模塊169傳統(tǒng)的依賴方向設(shè)計(jì)原則則:依賴賴倒置原原則高層依賴賴低層的的問(wèn)題抽象層包包含的是是系統(tǒng)的的業(yè)務(wù)邏邏輯和宏宏觀的、、戰(zhàn)略性性的決定定,是必必然性的的體現(xiàn)具體層則則含有與與實(shí)現(xiàn)相相關(guān)的算算法和邏邏輯,以以及戰(zhàn)術(shù)術(shù)性的決決定,帶帶有相當(dāng)當(dāng)大的偶偶然性選選擇。具具體層經(jīng)經(jīng)常有變變動(dòng),難難免出現(xiàn)現(xiàn)錯(cuò)誤必然依賴賴偶然,,穩(wěn)定依依賴變動(dòng)動(dòng)?170設(shè)計(jì)原則則:依賴賴倒置原原則依賴具體體的缺點(diǎn)點(diǎn)171設(shè)計(jì)原則則:依賴賴倒置原原則依賴抽象象抽象一般般不會(huì)變變動(dòng)這樣代碼碼不會(huì)受受易變的的具體層層影響172設(shè)計(jì)原則則:針對(duì)對(duì)接口編編程如何做到到“依賴賴倒置””?“Programtoaninterface,notanimplementation”173設(shè)計(jì)原則6:針對(duì)接口編程要針對(duì)接口編程不要針對(duì)實(shí)現(xiàn)編程設(shè)計(jì)原則則:針對(duì)對(duì)接口編編程“針對(duì)接接口編程程”的一一些建議議變量、參參數(shù)、返返回值等等應(yīng)聲明明為抽象象類(lèi)不要繼承承非抽象象類(lèi)不要重載載父類(lèi)的的非抽象象方法當(dāng)然這些些只是建建議實(shí)際情況況要權(quán)衡衡利弊174FactoryMethod(工廠方法法)模式“女?huà)z摶土土造人””《風(fēng)俗通》:“俗說(shuō)說(shuō)天開(kāi)地地辟,未未有人民民。女?huà)z媧摶黃土土為人。?!?75FactoryMethod(工廠方法法)模式簡(jiǎn)單工廠廠:根據(jù)傳入入的參數(shù)數(shù),決定定創(chuàng)建哪哪一個(gè)產(chǎn)產(chǎn)品類(lèi)對(duì)對(duì)象176Human*NvWa::CreateHuman((stringname){{if(name==““ZhangSan"")returnnewZhangSan;elseif(name==““LiSi"))returnnewLiSi;elseif(name===““WangErMaZi"))returnnewWangErMaZi;}FactoryMethod(工廠方法法)模式簡(jiǎn)單工廠廠的優(yōu)缺缺點(diǎn)優(yōu)點(diǎn):實(shí)現(xiàn)了責(zé)責(zé)任分割割利用判斷斷邏輯,,決定實(shí)實(shí)例化哪哪一個(gè)產(chǎn)產(chǎn)品類(lèi)客戶端可可以免除除直接創(chuàng)創(chuàng)建產(chǎn)品品類(lèi)對(duì)象象的責(zé)任任,僅僅僅使用該該產(chǎn)品缺點(diǎn):沒(méi)有完全全做到““開(kāi)-閉”一旦增加加新的產(chǎn)產(chǎn)品,需需要修改改工廠的的代碼但是客戶戶代碼不不需要修修改“我不入入地獄誰(shuí)誰(shuí)入地獄獄”177FactoryMethod(工廠方法法)模式“女?huà)z舉舉繩造人人”“女?huà)z摶摶土為人人,劇務(wù)務(wù),力不不暇供,,乃引繩繩于桓泥泥中,舉舉以為人人?!?78FactoryMethod(工廠方法法)模式簡(jiǎn)單工廠廠的問(wèn)題題所有具體體產(chǎn)品對(duì)對(duì)象的創(chuàng)創(chuàng)建都放放在一個(gè)個(gè)類(lèi)中,,一旦增增加新的的產(chǎn)品,,當(dāng)然工工廠類(lèi)要要被修改改工廠方法法:使用用多態(tài)來(lái)來(lái)應(yīng)對(duì)提供一個(gè)個(gè)抽象工工廠的接接口具體工廠廠分別負(fù)負(fù)責(zé)創(chuàng)建建具體產(chǎn)產(chǎn)品對(duì)象象增加新的的產(chǎn)品只只需要相相應(yīng)增加加新的具具體工廠廠類(lèi)179FactoryMethod(工廠方法法)模式意圖定義一個(gè)個(gè)用于創(chuàng)創(chuàng)建對(duì)象象的接口口,讓子子類(lèi)決定定實(shí)例化化哪一個(gè)個(gè)類(lèi)使一個(gè)類(lèi)類(lèi)的實(shí)例例化延遲遲到其子子類(lèi)優(yōu)點(diǎn)封裝了創(chuàng)創(chuàng)建具體體對(duì)象的的工作使得客戶戶代碼““針對(duì)接接口編程程”,保保持對(duì)變變化的““關(guān)閉””180FactoryMethod(工廠方法法)模式工廠方法法應(yīng)用到到“快餐餐店”問(wèn)問(wèn)題181Fa?ade((門(mén)面、外外觀)模式例1:傳統(tǒng)的的醫(yī)院::病人需要要直接跟跟各個(gè)部部門(mén)打交交道182門(mén)診掛號(hào)劃價(jià)化驗(yàn)取藥Fa?ade((門(mén)面)模式人性化的的醫(yī)院接待員代代替病人人進(jìn)行掛掛號(hào)、劃劃價(jià)等病人只需需要和接接待員打打交道183門(mén)診掛號(hào)劃價(jià)取藥接待員醫(yī)院的門(mén)門(mén)面(Facade)Fa?ade((門(mén)面)模式例2:組建家家庭影院院184Fa?ade((門(mén)面)模式欣賞一部部電影的的

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論