




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
設(shè)計原則與設(shè)計模式設(shè)計原則與設(shè)計模式設(shè)計模式的思想根源是基本原則的宏觀運用,本質(zhì)上是沒有任何模式的發(fā)現(xiàn)模式的人永遠是大師,而死守模式的人,最多只能是一個工匠.2設(shè)計模式DesignPattern設(shè)計模式的思想根源是基本原則的宏觀運用,本質(zhì)上是沒有任何模式2設(shè)計模式DesignPattern面向?qū)ο笱芯康男骂I(lǐng)域20世紀(jì)90年代,面向?qū)ο蠓椒ㄅc技術(shù)在國內(nèi)軟件業(yè)界十分火爆,人們熱衷于談?wù)摗皩ο蟆辈⒁詾闃s。十多年來,人們發(fā)表、出版了無數(shù)的文章和書籍。現(xiàn)在,該寫的似乎都寫完了,沒有新花樣玩了,真是一片無聊設(shè)計模式(DesignPattern)及時問世,面向?qū)ο髳酆谜邆兘K于有了新的追求3設(shè)計模式DesignPattern面向?qū)ο笱芯康男骂I(lǐng)域3設(shè)計模式:起源起源ChristopherAlexander當(dāng)代著名建筑大師加州大學(xué)伯克利分校建筑學(xué)教授、環(huán)境結(jié)構(gòu)研究所所長、美國藝術(shù)與科學(xué)院院士在建筑、室內(nèi)、計算機、家具設(shè)計甚至哲學(xué)方面都卓有建樹著作:《APatternLanguage》、《TheTimelessWayofBuilding》4設(shè)計模式:起源起源44設(shè)計模式:起源Gof(GangOfFour,“四人幫”)ErichGamma,RichardHelm,RalphJohnson,JohnVlissides1995年出版了《DesignPatterns:ElementsofReusableObject-OrientedSoftware》該書確立了設(shè)計模式這個術(shù)語,創(chuàng)導(dǎo)了一種新的面向?qū)ο笤O(shè)計思潮。從此,參與設(shè)計模式研究的人數(shù)爆炸性地增長5設(shè)計模式:起源Gof(GangOfFour,“四人幫”5設(shè)計模式:起源6設(shè)計模式:起源66設(shè)計模式什么叫模式?“每一個模式描述了在我們周圍不斷重復(fù)發(fā)生的問題,以及該問題的解決方案的核心。這樣,你就能一次又一次地使用該解決方案而不必重復(fù)勞動”盡管軟件技術(shù)發(fā)展非??欤侨匀挥蟹浅6嗟脑O(shè)計模式可以讓我們套用設(shè)計模式可以幫助人們簡便地復(fù)用以前成功的設(shè)計方案,提高工作效率7設(shè)計模式什么叫模式?77設(shè)計模式:研究現(xiàn)狀設(shè)計模式的研究現(xiàn)狀pattern與Java、C#pattern與組件技術(shù)(如CORBA)pattern與系統(tǒng)結(jié)構(gòu)pattern與泛型編程(genericprogramming)相結(jié)合其他(例如UML等)8設(shè)計模式:研究現(xiàn)狀設(shè)計模式的研究現(xiàn)狀88模式的分類(gof提出的23個)9創(chuàng)建型結(jié)構(gòu)型行為型類FactoryMethodAdapter(類)InterpreterTemplateMethod
對象AbstractFactoryBuilderPrototypeSingletonAdapter(對象)BridgeCompositeDecoratorFacadeFlyweightProxyChainofResponsibilityCommandIteratorMediatorMementoObserverStateStrategyVisitor模式的分類(gof提出的23個)9創(chuàng)建型結(jié)構(gòu)型行為型類Fac9Bridge(橋梁)模式案例有一個叫做HuntBird的游戲,里面需要表示各種各樣的鳥類10Bridge(橋梁)模式案例1010Bridge(橋梁)模式最初的設(shè)計11Bridge(橋梁)模式最初的設(shè)計1111Bridge(橋梁)模式需求變化:鳥類要會飛12Bridge(橋梁)模式需求變化:鳥類要會飛1212Bridge(橋梁)模式如果增加一種鳥類“企鵝”呢?13Bridge(橋梁)模式如果增加一種鳥類“企鵝”呢?1313Bridge(橋梁)模式改進方法:對“飛”使用多態(tài)14Bridge(橋梁)模式改進方法:對“飛”使用多態(tài)1414Bridge(橋梁)模式改進方法:再次使用繼承15Bridge(橋梁)模式改進方法:再次使用繼承1515Bridge(橋梁)模式如果增加“游泳”行為呢?16Bridge(橋梁)模式如果增加“游泳”行為呢?1616Bridge(橋梁)模式繼承只會使得問題越來越復(fù)雜繼承是面向?qū)ο蟮幕痉▽毎???OO=類+對象+繼承+消息通信17設(shè)計原則1:組合優(yōu)先優(yōu)先使用組合,而不是繼承Bridge(橋梁)模式繼承只會使得問題越來越復(fù)雜17設(shè)計原17設(shè)計原則:組合優(yōu)先繼承復(fù)用的優(yōu)點可以很容易的修改或擴展父類的實現(xiàn)18設(shè)計原則:組合優(yōu)先繼承復(fù)用的優(yōu)點1818設(shè)計原則:組合優(yōu)先繼承復(fù)用的缺點繼承破壞封裝,因為父類的實現(xiàn)細節(jié)完全暴露給子類(白盒復(fù)用)父類的實現(xiàn)發(fā)生改變,則子類必受牽連繼承是靜態(tài)的,不能在運行時發(fā)生改變,不靈活19設(shè)計原則:組合優(yōu)先繼承復(fù)用的缺點1919設(shè)計原則:組合優(yōu)先組合復(fù)用的優(yōu)點不破壞封裝,這種復(fù)用是黑盒復(fù)用,因為成員對象的內(nèi)部細節(jié)對新對象保密所需依賴少(只依賴接口)是動態(tài)的,可以把成員對象動態(tài)替換為另一個類型相同的對象組合復(fù)用的缺點對象數(shù)量會增加使用委托(delegation)會使得系統(tǒng)復(fù)雜20設(shè)計原則:組合優(yōu)先組合復(fù)用的優(yōu)點2020設(shè)計原則:組合優(yōu)先組合優(yōu)先Favorcompositionoverinheritance當(dāng)需要應(yīng)對變化的時候,應(yīng)該首先使用組合的方式,而不是繼承因為組合更加靈活例1:汽車有很多種,小轎車、貨車、客車,有的車是客貨兩用,有的車水陸兩用21設(shè)計原則:組合優(yōu)先組合優(yōu)先2121設(shè)計原則:組合優(yōu)先如果使用繼承來描述:一旦增加新的汽車種類或用途,都需要大量改動原有代碼22設(shè)計原則:組合優(yōu)先如果使用繼承來描述:2222設(shè)計原則:組合優(yōu)先使用“組合”思路考慮問題“汽車”擁有某種或某些“用途”“汽車”和“用途”獨立變化,互不影響23設(shè)計原則:組合優(yōu)先使用“組合”思路考慮問題2323設(shè)計原則:組合優(yōu)先區(qū)分“Is-A”與“Has-A”有一個系統(tǒng)需要描述經(jīng)理、雇員和學(xué)生它們都是人,所以:24設(shè)計原則:組合優(yōu)先區(qū)分“Is-A”與“Has-A”2424設(shè)計原則:組合優(yōu)先問題有些人既是經(jīng)理,又是學(xué)生,比如某位在讀MBA的老總25設(shè)計原則:組合優(yōu)先問題2525設(shè)計原則:組合優(yōu)先換一個角度看問題雇員、經(jīng)理、學(xué)生其實都是角色的一種人擁有角色26設(shè)計原則:組合優(yōu)先換一個角度看問題2626Bridge(橋梁)模式是什么導(dǎo)致設(shè)計的不完美?變化,無法避免的、經(jīng)常的需求變化設(shè)計者的理想當(dāng)需求變化的時候,盡可能少的修改代碼就可以滿足新的需求27設(shè)計原則2:封裝可變性發(fā)現(xiàn)代碼容易變化的部分,封裝之,使它和不容易變化的部分獨立開來Bridge(橋梁)模式是什么導(dǎo)致設(shè)計的不完美?27設(shè)計原則27Bridge(橋梁)模式“發(fā)現(xiàn)變化點”28Bridge(橋梁)模式“發(fā)現(xiàn)變化點”2828Bridge(橋梁)模式“封裝變化點”變化點1:小鳥一家29Bridge(橋梁)模式“封裝變化點”2929Bridge(橋梁)模式“封裝變化點”變化點2:鳥類的行為——飛30Bridge(橋梁)模式“封裝變化點”3030Bridge(橋梁)模式“封裝變化點”變化點2:鳥類的行為——游泳31Bridge(橋梁)模式“封裝變化點”3131Bridge(橋梁)模式“使變化點和不變點獨立開來”在這個例子里其實是兩個變化點相獨立“鳥類”和“行為”什么關(guān)系?鳥類擁有行為鳥類行為的具體實現(xiàn),委托“行為”類來完成32Bridge(橋梁)模式“使變化點和不變點獨立開來”3232鳥兒擁有飛、游泳的行為33鳥兒擁有飛、游泳的行為3333Bridge(橋梁)模式使用橋梁模式的效果比如增加一種鳥類“鵝”,相應(yīng)的要增加一種游泳的行為“紅掌撥清波”只需要增加一個鳥類的子類“鵝”增加一個游泳的行為“紅掌撥清波”設(shè)置“鵝”的飛翔行為為“飛不起來”設(shè)置“鵝”的游泳行為為“紅掌撥清波”原有代碼不需要改動!34Bridge(橋梁)模式使用橋梁模式的效果3434Bridge(橋梁)模式35Bridge(橋梁)模式3535Bridge(橋梁)模式使用橋梁模式的效果當(dāng)需求改變的時候(增加動物或行為),只需要簡單添加幾個類對原有代碼不需要改動保證了代碼的穩(wěn)定,提高了可維護性36設(shè)計原則3:開-閉原則在設(shè)計一個軟件的時候,應(yīng)當(dāng)使這個軟件可以在不被修改的前提下擴展Bridge(橋梁)模式使用橋梁模式的效果36設(shè)計原則3:開36Bridge(橋梁)模式結(jié)構(gòu)37Bridge(橋梁)模式結(jié)構(gòu)3737Bridge(橋梁)模式意圖將抽象部分與它的實現(xiàn)部分分離,使它們都可以獨立地變化適用性抽象和它的實現(xiàn)部分可以獨立變化類的抽象以及它的實現(xiàn)都可以通過生成子類的方法加以擴充實現(xiàn)部分的修改不會對客戶產(chǎn)生影響......38Bridge(橋梁)模式意圖3838Bridge(橋梁)模式應(yīng)用舉例1:“小朋友畫畫”使用蠟筆需要大中小三種型號每種型號各有12種顏色共36支39Bridge(橋梁)模式應(yīng)用舉例1:“小朋友畫畫”3939Bridge(橋梁)模式使用毛筆:大、中、小3支毛筆12種顏料40Bridge(橋梁)模式使用毛筆:4040Bridge(橋梁)模式蠟筆和毛筆的差別蠟筆:筆和顏色無法分離,因此需要36種蠟筆毛筆:筆和顏色可以獨立選擇,因此只有3+12=15個子類體現(xiàn)了Bridge模式將繼承關(guān)系轉(zhuǎn)換為組合關(guān)系,從而降低了系統(tǒng)間的耦合,減少了代碼冗余41Bridge(橋梁)模式蠟筆和毛筆的差別4141Bridge(橋梁)模式應(yīng)用舉例2有一個CAD軟件,可以畫多種圖形同時支持多套繪圖算法傳統(tǒng)的設(shè)計42Bridge(橋梁)模式應(yīng)用舉例24242Bridge(橋梁)模式應(yīng)用Bridge模式43Bridge(橋梁)模式應(yīng)用Bridge模式4343Bridge(橋梁)模式分析圖形Shape是一個抽象概念,它可以有許多具體化(變化點1)圖形的顯示Drawing是圖形的實現(xiàn),它也可以有許多套算法(變化點2)Bridge模式使用組合代替繼承,避免了復(fù)雜的繼承體系,使得兩個變化點獨立變化,互不影響44Bridge(橋梁)模式分析4444設(shè)計原則:開-閉原則、封裝可變性“開-閉”原則BertrandMeyer:“Softwareshouldbeopenforextension,butclosedformodification”在設(shè)計一個軟件的時候,應(yīng)當(dāng)使這個軟件可以在不被修改的前提下擴展解釋已有模塊,尤其是最重要的抽象層模塊不能動:保證穩(wěn)定性和延續(xù)性可以擴展新模塊:增加新行為,保證靈活性45設(shè)計原則:開-閉原則、封裝可變性“開-閉”原則4545設(shè)計原則:開-閉原則、封裝可變性BertrandMeyer對象技術(shù)大師法國工程院院士蘇黎世工學(xué)院計算機系教授發(fā)明了Eiffel語言和按契約設(shè)計(DesignbyContract)的思想早年參與了Z形式語言的設(shè)計名著《面向?qū)ο筌浖?gòu)造》46設(shè)計原則:開-閉原則、封裝可變性BertrandMeyer46設(shè)計原則:開-閉原則、封裝可變性玉帝遵照“開-閉”原則維護天庭秩序當(dāng)年孫悟空大鬧天空,向天庭發(fā)出挑戰(zhàn):“皇帝輪流做,明年到我家......只教他搬出去,將天宮讓與我!”太白金星給玉皇大帝 建議道:“降一道招安 圣旨,把他宣來上界... 與他籍名在箓... 一則不動眾勞師, 二則收仙有道也。”47設(shè)計原則:開-閉原則、封裝可變性玉帝遵照“開-閉”原則維護天47設(shè)計原則:開-閉原則、封裝可變性分析“不動眾勞師”、不破壞天規(guī)就是“閉”收仙有道就是“開”招安,就是玉帝的“開-閉”原則:既讓孫悟空滿意,又不必更改天庭現(xiàn)有的秩序48設(shè)計原則:開-閉原則、封裝可變性分析4848設(shè)計原則:開-閉原則、封裝可變性分析現(xiàn)有的天庭秩序是系統(tǒng)的最高抽象層弼馬溫這個職位只是具體的實現(xiàn)層招安的關(guān)鍵就是不允許更改現(xiàn)有的天庭秩序,但是允許將妖猴納入到文武百官中,從而擴展了這一秩序的具體實現(xiàn)49設(shè)計原則:開-閉原則、封裝可變性分析4949設(shè)計原則:開-閉原則、封裝可變性“封裝可變性原則”gof:“考慮你的設(shè)計中什么可能會發(fā)生變化......考慮你允許什么發(fā)生變化而不讓這一變化導(dǎo)致重新設(shè)計”Shalloway:“發(fā)現(xiàn)變化點,并封裝之”一種可變性不應(yīng)散落在代碼的很多角落一種可變性不應(yīng)當(dāng)與另一種可變性混合在一起50設(shè)計原則:開-閉原則、封裝可變性“封裝可變性原則”5050設(shè)計原則:開-閉原則、封裝可變性設(shè)計模式對“開-閉”原則的支持比如Bridge橋梁模式:將抽象部分和實現(xiàn)部分分別封裝,可以分別獨立變化51設(shè)計原則:開-閉原則、封裝可變性設(shè)計模式對“開-閉”原則的支51設(shè)計原則:開-閉原則、封裝可變性對“開-閉”原則支持的不好的例子java.util.Calendar52java提供的描述歷法的抽象類描述公歷的子類我們希望再派生出一個子類,用于描述陰歷設(shè)計原則:開-閉原則、封裝可變性對“開-閉”原則支持的不好的52設(shè)計原則:開-閉原則、封裝可變性問題:Calendar只定義了適用于公歷的常量和方法53publicfinalstaticintSUNDAY=1;publicfinalstaticintMONDAY=2;...publicfinalstaticintJANUARY=0;publicfinalstaticintFEBRUARY=1;...publicvoidsetFistDayOfWeek(intvalue);publicintgetFirstDayOfWeek();...設(shè)計原則:開-閉原則、封裝可變性問題:53publicfi53設(shè)計原則:開-閉原則、封裝可變性問題英文的星期、月份名稱不符合中國陰歷的叫法陰歷以10天為一周,公歷和陰歷每月的天數(shù)也不同,所以Calendar關(guān)于星期、月份的算法不適合陰歷總之,Calendar無法容納中國陰歷,因此不支持“開-閉”原則54設(shè)計原則:開-閉原則、封裝可變性問題5454Strategy(策略)模式橋梁模式使得兩個變化點的獨立55Strategy(策略)模式橋梁模式5555設(shè)計原則找出應(yīng)用中可能需要變化之處把它們獨立出來不要和那些不需要變化的代碼混在一起56設(shè)計原則找出應(yīng)用中可能需要變化之處5656Strategy(策略)模式單獨看飛的行為的實現(xiàn)策略模式:封裝了一系列算法,使得它們可以相互替換效果:算法可以獨立變化57Strategy(策略)模式單獨看飛的行為的實現(xiàn)5757設(shè)計原則針對接口編程,而不是針對實現(xiàn)編程58設(shè)計原則針對接口編程,而不是針對實現(xiàn)編程5858策略模式-開閉原則.例-計算價格PublicclassPart{privatedoublebasePrice;publicvoidsetPrice(doubleprice){basePrice=price;}publicdoublegetPrice(){returnbasePrice;}}59策略模式-開閉原則.例-計算價格PublicclassP59某類方法Publicdoubletotalprice(Part[]parts){doubletotal=0.0;for(inti=0;i<parts.length;i++){total+=parts[i].getPrice();}returntotal;}60某類方法Publicdoubletotalprice(P60思考內(nèi)存折扣?61思考內(nèi)存折扣?6161方法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方法Publicdoubletotalprice(Par62思考符合OCP嗎?63思考符合OCP嗎?6363方法?PublicclassMemoryextendsPart{publicdoublegetPrice(){returnbasePrice*0.9;}}64方法?PublicclassMemoryextends64更好的方法?采用一個PricePolicy類,通過對其進行繼承以提供不同的計價策略65更好的方法?采用一個PricePolicy類,通過對其進行繼65方法PublicclassPart{privatePricePolicypricePolicy;publicvoidsetPricePolicy(PricePolicypolicy){pricePolicy=policy;}publicvoidsetPrice(doubleprice){pricePolicy.setPrice(price);}publicdoublegetPrice(){returnpricePolicy.getPrice();}}66方法PublicclassPart{6666價格策略PublicclassPricePolicy{privatedoublebasePrice;publicvoidsetPrice(doubleprice){basePrice=price;}publicdoublegetPrice(){returnbasePrice;}}67價格策略PublicclassPricePolicy{667銷售策略PublicclassSaleextendsPricePolicy{privatedoublediscount;publicvoidsetDiscount(doublediscount){this.discount=discount;}publicdoublegetPrice(){returnbasePrice*discount;}}68銷售策略PublicclassSaleextends68Strategy(策略):定義所有支持的算法的公共接口ConcreteStrategy(具體策略):實現(xiàn)具體算法Context(上下文):用一個ConcreteStrategy對象來配置維護一個對Strategy對象的引用可定義一個接口來讓Strategy訪問它的數(shù)據(jù)69Strategy(策略):定義所有支持的算法的公共接口69階段小結(jié)設(shè)計原則70限制變化的影響范圍增加新功能,要做到只增加新代碼,而不改動老代碼盡量用組合,而不是繼承組合優(yōu)先開-閉原則封裝可變性階段小結(jié)設(shè)計原則70限制變化的影響范圍增加新功能,要做到只增70階段小結(jié)策略模式使得算法可以獨立變化使用組合取代繼承,封裝了可變性,保證了“開-閉”橋梁模式使得抽象和實現(xiàn)獨立變化避免了兩個變化點的耦合71階段小結(jié)策略模式7171Adapter(適配器)模式例子1:“不合適的插座”你的電腦的插頭是三相的而墻上的插座只有兩相的插頭和插座的“接口”不匹配,怎么辦?72Adapter(適配器)模式例子1:“不合適的插座”7272Adapter(適配器)模式例子2:HuntBird游戲中,希望增加一種鳥類“鴨子”但是發(fā)現(xiàn)以前有一個系統(tǒng)中已經(jīng)有了“鴨子”類,希望重用老代碼73Adapter(適配器)模式例子2:7373Adapter(適配器)模式新老代碼接口不一致74Adapter(適配器)模式新老代碼接口不一致7474Adapter(適配器)模式疑問把老代碼修改一下不就可以了么?如下:75Adapter(適配器)模式疑問7575Adapter(適配器)模式否定首先,老代碼不一定允許修改比如可能根本沒有代碼,只有鏈接庫其次,修改代碼工作量可能很大容易出錯還記得“開-閉原則”么76Adapter(適配器)模式否定7676Adapter(適配器)模式應(yīng)用(對象)適配器模式實現(xiàn)接口轉(zhuǎn)換77Adapter(適配器)模式應(yīng)用(對象)適配器模式實現(xiàn)接口轉(zhuǎn)77Adapter(適配器)模式理解1:接口轉(zhuǎn)換78客戶(鳥)被適配者(鴨子)適配器請求轉(zhuǎn)換后的請求Adapter(適配器)模式理解1:接口轉(zhuǎn)換78客戶(鳥)被78Adapter(適配器)模式79叫呷呷叫Adapter(適配器)模式79叫呷呷叫79Adapter(適配器)模式理解2:重新包裝,改變接口80Adapter(適配器)模式理解2:重新包裝,改變接口8080Adapter(適配器)模式類適配器81Adapter(適配器)模式類適配器8181Adapter(適配器)模式結(jié)構(gòu)對象Adapter82Adapter(適配器)模式結(jié)構(gòu)8282Adapter(適配器)模式結(jié)構(gòu)類Adapter83Adapter(適配器)模式結(jié)構(gòu)8383Adapter(適配器)模式意圖將一個類的接口轉(zhuǎn)換成客戶希望的另外一個接口Adapter模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作84Adapter(適配器)模式意圖8484Adapter(適配器)模式應(yīng)用舉例1我們打算編寫一個畫圖軟件其中畫圓形已經(jīng)有了一個現(xiàn)成的類但是接口不同,不能直接使用85Adapter(適配器)模式應(yīng)用舉例18585Adapter(適配器)模式使用對象Adapter86Adapter(適配器)模式使用對象Adapter8686Adapter(適配器)模式應(yīng)用舉例2缺省適配模式——“魯達剃度”凡是和尚都應(yīng)該如此:87Adapter(適配器)模式應(yīng)用舉例28787Adapter(適配器)模式但是魯智深并不是這樣88魯智深::習(xí)武(){
拳打鎮(zhèn)關(guān)西();
大鬧五臺山();
倒拔垂楊柳();
火燒瓦官寺();}Adapter(適配器)模式但是魯智深并不是這樣88魯智深:88Adapter(適配器)模式所以當(dāng)初魯達剃度時,眾僧說:“這個人形容丑惡,相貌兇頑,不可剃度”89?Adapter(適配器)模式所以當(dāng)初魯達剃度時,眾僧說:8989Adapter(適配器)模式但是長老卻說:“此人上應(yīng)天星,心地剛直。雖然時下兇頑,命中駁雜,久后卻得清靜。證過非凡,汝等皆不及他”90Adapter(適配器)模式但是長老卻說:9090Adapter(適配器)模式“天星”就是缺省適配器當(dāng)你不想/不能實現(xiàn)接口的所有方法時利用缺省適配器類,提供這些方法的缺省實現(xiàn)從這個類再派生出的子類就可以不去實現(xiàn)那些不想實現(xiàn)的方法了91Adapter(適配器)模式“天星”就是缺省適配器9191真實世界中的適配器想一想Java語言中不同版本中有沒有需要進行適配的92真實世界中的適配器想一想Java語言中不同版本中有沒有需要進92真實世界中的適配器早期java版本中集合(Collection)類型(例如:Vector,Stack,Hashtable)都實現(xiàn)了一個elements()方法。該方法返回一個Enumeration(枚舉)新版本中開始使用Iterator(迭代器)接口,這個接口和枚舉接口很像,但不同的是,迭代器還提供了刪除元素的能力。93真實世界中的適配器早期java版本中集合(Collectio93問題面對遺留代碼,這些代碼會暴露出枚舉器接口,但我們又希望在新的代碼中只使用迭代器。解決辦法構(gòu)造一個適配器將枚舉適配到迭代器94問題面對遺留代碼,這些代碼會暴露出枚舉器接口,但我們又希望在94959595969696publicclassEnumerationIteratorimplementsIterator{ //適配器看起來就是一個Iterator //我們使用組合的方式,將枚舉結(jié)合進適配器中,用實例變量記錄
Enumerationenumeration; publicEnumerationIterator(Enumerationenumeration){ this.enumeration=enumeration; } //迭代器的hasNext其實是委托給enumeration的hasMoreElements方法
publicbooleanhasNext(){ returnenumeration.hasMoreElements(); } //迭代器的next其實是委托給enumeration的nextElement方法
publicObjectnext(){ returnenumeration.nextElement(); } //很不幸,我們不能支持迭代器的remove方法,所以必須放棄,這里是拋出一個異常
publicvoidremove(){ thrownewUnsupportedOperationException(); }}97publicclassEnumerationIterat97實例有一個類(adaptee)實現(xiàn)了數(shù)學(xué)中的冪次運算,方法中需要傳入兩個參數(shù),一個是基數(shù)base,另外一個是冪次exp。現(xiàn)在客戶端需要一個求得一個數(shù)的平方的函數(shù)接口(target),傳入一個數(shù),得到它的平方值。為了復(fù)用已經(jīng)存在的類adaptee,使用Adapter來適配adaptee,adapter實現(xiàn)了target接口。98實例有一個類(adaptee)實現(xiàn)了數(shù)學(xué)中的冪次運算,方法中98999999在架構(gòu)層次上的應(yīng)用JDBC驅(qū)動軟件與適配器模式JDBC給出一個客戶端通用的界面。每個數(shù)據(jù)庫引擎的JDBC驅(qū)動軟件都是一個介于JDBC接口和數(shù)據(jù)庫引擎接口之間的適配器軟件抽象的JDBC接口和各個數(shù)據(jù)庫引擎的API之間都需要相應(yīng)的適配器軟件,即為各個數(shù)據(jù)庫引擎準(zhǔn)備的驅(qū)動軟件。
100在架構(gòu)層次上的應(yīng)用JDBC驅(qū)動軟件與適配器模式100100JDBC/ODBC橋梁如果沒有合適的JDBC驅(qū)動軟件,用戶也可以通過ODBC驅(qū)動軟件把JDBC通過一個JDBC/ODBC橋梁軟件與ODBC驅(qū)動軟件連接起來,從而達到連接數(shù)據(jù)庫的目的。101JDBC/ODBC橋梁101101設(shè)計原則:里氏代換原則例子1:“圓是不是橢圓?”在幾何學(xué)里,圓是橢圓的一種特殊情況因此,把橢圓看作父類,把圓作為子類102設(shè)計原則:里氏代換原則例子1:“圓是不是橢圓?”102102設(shè)計原則:里氏代換原則問題橢圓有長軸、短軸圓會完全繼承下來這些對于圓來說毫無意義類似的:“正方形不是矩形”103Circlecircle;circle.GetMajorAxis();設(shè)計原則:里氏代換原則問題103Circlecircle;103設(shè)計原則:里氏代換原則例子2:“企鵝不是鳥的子類”凡是鳥都會飛但是企鵝不會104設(shè)計原則:里氏代換原則例子2:“企鵝不是鳥的子類”104104設(shè)計原則:里氏代換原則例子3我們需要設(shè)計一個類FileName來描述文件名,而文件名不就是一個特殊的字符串么?所以我們?nèi)绱嗽O(shè)計:105設(shè)計原則:里氏代換原則例子3105105設(shè)計原則:里氏代換原則問題凡是字符串都支持相加操作,也就是說兩個字符串相加,結(jié)果還是一個字符串可是兩個文件名相加,還是一個合法的文件名么?比如:“c:\a.txt”+“d:\b.txt”結(jié)果是:“c:\a.txtd:\b.txt”106設(shè)計原則:里氏代換原則問題106106設(shè)計原則:里氏代換原則錯在哪里?墨子論“取譬”“白馬,馬也;乘白馬,乘馬也。驪馬,馬也;乘驪馬,乘馬也?!苯忉專喊遵R、驪馬(黑馬)都是馬,既然馬可以騎,那么白馬和驪馬肯定也可以騎107設(shè)計原則:里氏代換原則錯在哪里?107107設(shè)計原則:里氏代換原則LiskovSubstitutionPrinciple一個軟件如果使用的是一個父類的話,如果把該父類換成子類,它不能察覺出父類對象和子類對象的區(qū)別也就是凡是父類適用的地方子類也適用繼承只有滿足里氏代換原則才是合理的108設(shè)計原則4:里氏代換原則凡是父類適用的地方子類應(yīng)當(dāng)也適用設(shè)計原則:里氏代換原則LiskovSubstitution108設(shè)計原則:里氏代換原則反過來的代換不成立子類適用的地方不要求父類一定能適用墨子又說“娣,美人也,愛娣,非愛美人也......盜,人也,惡盜,非惡人也”妹妹是美女,哥哥喜歡妹妹,并不是因為喜歡美女小偷是人,討厭小偷,并不討厭所有人109設(shè)計原則:里氏代換原則反過來的代換不成立109109設(shè)計原則:里氏代換原則Java語言對此類問題的防范它的String類是final的,不能繼承正確的方法使用Adapter模式110設(shè)計原則:里氏代換原則Java語言對此類問題的防范110110設(shè)計原則:里氏代換原則Java中的反例它的Stack類是從Vector類繼承下來的“棧不就是施加了訪問限制的數(shù)組么?”所以“StackIs-AVector”111設(shè)計原則:里氏代換原則Java中的反例111111設(shè)計原則:里氏代換原則用里氏代換原則來判斷凡是數(shù)組行得通的地方,換成棧也行得通么?Vector可以隨機訪問,可以任意修改里面的元素...這些都是Stack所不允許的因此Stack不能從Vector繼承下來,它不能擁有Vector的接口112設(shè)計原則:里氏代換原則用里氏代換原則來判斷112112設(shè)計原則:里氏代換原則看看C++STL是怎么辦的STL中的stack其實是一個Adapter113template<classT,classCont=deque<T>>classstack{public:
void
push(constvalue_type&x){c.push_back(x);}
void
pop(){c.pop_back(x);}protected:Contc;};設(shè)計原則:里氏代換原則看看C++STL是怎么辦的113te113設(shè)計模式-工廠模式設(shè)計模式-工廠模式當(dāng)看到“new”,就會想到“具體”115當(dāng)看到“new”,就會想到“具體”115115116一個計算器例子publicclassOperation{ privatedoublenumberA=0; privatedoublenumberB=0; publicvirtualdoubleGetResult(){ doubleresult=0; returnresult; }}classOperationAdd:Operation{ publicoverridedoubleGetResult(){ doubleresult=0; result=numberA+numberB; returnresult;}116一個計算器例子publicclassOperati116當(dāng)遇到一群相關(guān)的具體類時,通常見到下面的代碼OperationcreateOperation(Stringoperate){
Operationoper;
switch(operate){case”+”:oper=newOperationAdd();break;case”=”:oper=newOperationSub();break;case”*”:oper=newOperationMul();break;……..}}117當(dāng)遇到一群相關(guān)的具體類時,通常見到下面的代碼117117如果計算器要增加更多的運算類型怎么辦?118如果計算器要增加更多的運算類型怎么辦?118118簡單工廠開始封裝創(chuàng)建對象的代碼建立一個簡單工廠當(dāng)需要Operation時,就叫工廠做一個119簡單工廠開始封裝創(chuàng)建對象的代碼119119定義簡單工廠120定義簡單工廠120120PublicclassOperationFactory{ publicstaticOperationcreateOperate(Stringoperate){ Operationoper=null; switch(operate){case”+”:oper=newOperationAdd();break;case”=”:oper=newOperationSub();break;case”*”:oper=newOperationMul();break;case”/”:oper=newOperationDiv();break;}returnoper;}}121簡單工廠實現(xiàn)PublicclassOperationFactory{121客戶端的實現(xiàn)
Operationoper;oper=OperationFactory.createOperate(“+”);oper.NumberA=1;oper.NumberB=2;doubleresult=oper.GetResult();122客戶端的實現(xiàn)122122簡單工廠模式的優(yōu)點123簡單工廠類中包含了必要的邏輯判斷,根據(jù)客戶端的選擇條件動態(tài)實例化相關(guān)的類,對于客戶端來說,去除了與具體產(chǎn)品的依賴。就像計算器,讓客戶端不用管該用哪個類的實例,只要把‘+’給工廠,工廠自動就給出了實例,客戶端只要去做運算就可以了,不同的實例會實現(xiàn)不同的運算。簡單工廠實現(xiàn)了責(zé)任的分割。簡單工廠模式的優(yōu)點123簡單工廠類中包含了必要的邏輯判斷,根123問題如果要加一個“求M數(shù)的N此方”的功能,就要在原有方法中加一個分支條件,就要修改原有的類,違背了開放-封閉原則,于是工廠方法就來了。124問題如果要加一個“求M數(shù)的N此方”的功能,就要在原有方法中加124定義工廠方法模式工廠方法模式定義了一個創(chuàng)建對象的接口由子類決定實例化的類是哪一個工廠方法使一個類的實例化延遲到其子類。125定義工廠方法模式工廠方法模式定義了一個創(chuàng)建對象的接口125125遵循倒置依賴原則的指導(dǎo)方針變量不可以持有具體類的引用如果使用new,就會持有具體類的引用可以改用工廠來避開這樣的做法不要讓類派生自具體類如果派生自具體類,就會依賴具體類請派生自一個抽象(接口或抽象類)不是隨時都要遵循這個原則如直接實例化字符串對象126遵循倒置依賴原則的指導(dǎo)方針變量不可以持有具體類的引用126126應(yīng)用依賴倒置原則要依賴抽象,不要依賴具體類我們把工廠類抽象出一個接口,這個接口只有一個方法,就是創(chuàng)建抽象產(chǎn)品的工廠方法。然后,所有的要生產(chǎn)具體類的工廠,就去實現(xiàn)這個接口。這樣,一個簡單工廠模式的工廠類,就變成了一個工廠抽象接口和多個具體生產(chǎn)對象的工廠。于是,我們要增加‘求M數(shù)的N次方’的功能時,就不需要更改原有的工廠類了,只需要增加此功能的運算類和相應(yīng)的工廠類就可以了。127應(yīng)用依賴倒置原則要依賴抽象,不要依賴具體類127127工廠方法模式實現(xiàn)128工廠方法模式實現(xiàn)128128工廠方法模式實現(xiàn)先構(gòu)建一個工廠接口InterfaceIFactory{OperationCreateOperation();}129工廠方法模式實現(xiàn)先構(gòu)建一個工廠接口129129然后加減乘除各建一個具體工廠去實現(xiàn)這個接口classAddFactory:IFactory{publicOperationCreateOperation(){returnnewOperationAdd();}}classSubFactory:IFactory{publicOperationCreateOperation(){ returnnewOperationSub();}}130工廠方法模式實現(xiàn)然后加減乘除各建一個具體工廠去實現(xiàn)這個接口130工廠方法模式130然后加減乘除各建一個具體工廠去實現(xiàn)這個接口classMulFactory:IFactory{publicOperationCreateOperation(){returnnewOperationMul();}}classDivFactory:IFactory{publicOperationCreateOperation(){returnnewOperationDiv();}}131工廠方法模式實現(xiàn)然后加減乘除各建一個具體工廠去實現(xiàn)這個接口131工廠方法模式131客戶端的實現(xiàn)
IFactoryoperFactory=newAddFactory();Operationoper=operFactory.CreateOperation();oper.NumberA=1;oper.NumberB=2;doubleresult=oper.GetResult();132工廠方法模式實現(xiàn)客戶端的實現(xiàn)132工廠方法模式實現(xiàn)132工廠方法模式實現(xiàn)時,客戶端需要決定實例化哪一個工廠來實現(xiàn)運算類,選擇判斷的問題還是存在的,也就是說,工廠方法把簡單工廠的內(nèi)部邏輯判斷轉(zhuǎn)移到了客戶端代碼來進行。如果要加功能,本來是改工廠類的,而現(xiàn)在是修改客戶端。133工廠方法模式工廠方法模式實現(xiàn)時,客戶端需要決定實例化哪一個工廠來實現(xiàn)運算133
一個抽象產(chǎn)品類,可以派生出多個具體產(chǎn)品類。
一個抽象工廠類,可以派生出多個具體工廠類。
每個具體工廠類只能創(chuàng)建一個具體產(chǎn)品類的實例。134工廠方法模式 一個抽象產(chǎn)品類,可以派生出多個具體產(chǎn)品類。
一個抽象134雷鋒工廠雷鋒是眾人皆知的做好人好事的模范。作為一名大學(xué)生,每個人都可以以雷鋒做好事的名義去幫助老人。在這里,’雷鋒’類,擁有掃地、洗衣、買米等方法?!畬W(xué)雷鋒的大學(xué)生’類是‘雷鋒’類的一個繼承。而大學(xué)生是要畢業(yè)的,幫助老人是長期的,所以‘社區(qū)志愿者’更適合。于是,增加一個繼承‘雷鋒’類的‘社區(qū)志愿者’類。135雷鋒工廠雷鋒是眾人皆知的做好人好事的模范。135135雷鋒類classLeiFeng{ publicvoidSweep(){ Console.WriteLine(“掃地”); } publicvoidWash(){ Console.WriteLine(“洗衣”); } publicvoidBuyRice(){ Console.WriteLine(“買米”); }}136雷鋒類classLeiFeng{136136大學(xué)生類及社區(qū)志愿者classUndergraduate:LeiFeng{}classVolunteer:LeiFeng{}137大學(xué)生類及社區(qū)志愿者classUndergraduate137簡單工廠模式ClassSimpleFactory{publicstaticLeiFengCreateLeiFeng(stringtyple){LeiFengresult=null;switch(type){case”學(xué)雷鋒的大學(xué)生”:result=newUndergradute();break;case”社區(qū)志愿者”:result=newVolunteer();break;}returnresult;}}138簡單工廠模式ClassSimpleFactory{138138客戶端的實現(xiàn)LeiFengstudentA=SimpleFacatory.CreateLeiFeng(“學(xué)雷鋒的大學(xué)生”);studentA.BuyRice();LeiFengstudentB=SimpleFacatory.CreateLeiFeng(“學(xué)雷鋒的大學(xué)生”);studentB.Sweep();LeiFengstudentC=SimpleFacatory.CreateLeiFeng(“學(xué)雷鋒的大學(xué)生”);studentC.Wash();139簡單工廠模式客戶端的實現(xiàn)139簡單工廠模式139在這里,需要再任何實例化的時候?qū)懗鲞@個工廠的代碼。這里有重復(fù),于是用工廠方法模式來寫。140在這里,需要再任何實例化的時候?qū)懗鲞@個工廠的代碼。這里有重復(fù)140工廠方法模式InterfaceIFactory{LeiFengCreateLeiFeng();}classUndergraduteFactory:IFactory{publicLeiFengCreateLeiFeng(){returnnewUndergraduate();}}141工廠方法模式InterfaceIFactory141141classVolunteerFactory:IFactory{publicLeiFengCreateLeiFeng(){returnnewVolunteer();}}客戶端代碼
Ifactoryfactory=newUndergraduateFactory(); LeiFengstudentA=factory.CreateLeiFeng(); LeiFengstudentB=factory.CreateLeiFeng(); LeiFengstudentC=factory.CreateLeiFeng();studentA.BuyRice();studentB.Sweep();studentC.Wash();142工廠方法模式classVolunteerFactory:IFacto142在這里,盡管如果要換成‘社區(qū)志愿者’也還是要修改代碼,但只用修改一處就可以。工廠方法克服了簡單工廠違背開放-封閉原則的缺點,又保持了封裝對象創(chuàng)建過程的優(yōu)點。它們都是集中封裝了對象的創(chuàng)建,使得要更換對象時,不需要做大的改動就可實現(xiàn),降低了客戶程序與產(chǎn)品對象的耦合。143工廠方法模式在這里,盡管如果要換成‘社區(qū)志愿者’也還是要修改代碼,但只用143工廠方法模式是簡單工廠模式的進一步抽象和推廣,由于使用了多態(tài)性,工廠方法模式保持了簡單工廠模式的優(yōu)點,而且克服了它的缺點。但缺點是由于每加一個產(chǎn)品,就需要加一個產(chǎn)品工廠的類,增加了額外了開發(fā)量。144工廠方法模式工廠方法模式是簡單工廠模式的進一步抽象和推廣,由于使用了多態(tài)144抽象工廠模式提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無需指定它們具體的類。145抽象工廠模式提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無145定義抽象工廠模式146定義抽象工廠模式146146數(shù)據(jù)訪問程序用戶類User,假設(shè)只有ID和Name兩個字段。SqlserverUser類和AccessUser類,用于操作User表,假設(shè)只有“新增用戶”和“得到用戶”方法。SqlserverUser類,用于訪問SQLServer的用戶。AccessUser類,用于訪問Access的用戶。147數(shù)據(jù)訪問程序用戶類User,假設(shè)只有ID和Name兩個字段。147用工廠方法模式的數(shù)據(jù)訪問程序148用工廠方法模式的數(shù)據(jù)訪問程序148148InterfaceIUser{voidInsert(Useruser);UserGetUser(intid);}classSqlserverUser:IUser{
publicvoidInsert(Useruser){Console.WriteLine(“在SQLServer中給User表增加一條記錄”);}publicvoidGetUser(intid){Console.WriteLine(“在SQLServer中根據(jù)ID得到User表的一條記錄”);returnnull;}}149用工廠方法模式的數(shù)據(jù)訪問程序InterfaceIUser149用工廠方法模式的數(shù)據(jù)訪問149classAccessUser:IUser{
publicvoidInsert(Useruser){Console.WriteLine(“在Access中給User表增加一條記錄”);}publicvoidGetUser(intid){Console.WriteLine(“在Access中根據(jù)ID得到User表的一條記錄”);returnnull;}}150classAccessUser:IUser150150工廠方法IFactory接口:定義一個創(chuàng)建訪問User表對象的抽象的工廠接口。InterfaceIFactory{IuserCreateUser();}151工廠方法151151SqlServerFactory類,AccessFactory類實現(xiàn)接口classSqlServerFactory:IFactory{publicIuserCreateUser(){returnnewSqlserverUser();}}classAccessFactory:IFactory{publicIuserCreateUser(){returnnewAccessUser();}}152SqlServerFactory類,AccessFacto152客戶端實現(xiàn)StaticvoidMain(string[]args){Useruser=newUser();Ifactoryfactory=newSqlServerFactory();Iuseriu=factory.CreateUser();iu.Insert(user);iu.GetUser(1);Console.Read();}153客戶端實現(xiàn)StaticvoidMain(string[]153用抽象工廠模式的數(shù)據(jù)訪問程序154用抽象工廠模式的數(shù)據(jù)訪問程序154154Idepartment接口,用于客戶端訪問,解除與具體數(shù)據(jù)庫訪問的耦合。interfaceIDepartment{voidInsert(Departmentdepartment);DepartmentGetDepartment(intid);}SqlserverDepartment類,AccessDepartment類分別用于訪問SQLSever、Access的Department。155Idepartment接口,用于客戶端訪問,解除與具體數(shù)據(jù)庫155classSqlserverDepartment:IDepartment{publicvoidInsert(Departmentdepartment){Console.WriteLine(“在SQLServer中的Department表
增加一條記錄”);}publicDepartmentGetDepartment(intid){Console.WriteLine(“在SQLServer中根據(jù)ID得到 Department表中的一條記錄”);returnnull;}}156classSqlserverDepartment:ID156classAccessDepartment:IDepartment{publicvoidInsert(Departmentdepartment){Console.WriteLine(“在Access中的Department表增加
一條記錄”);}publicDepartmentGetDepartment(intid){Console.WriteLine(“在Access中根據(jù)ID得到 Department表中的一條記錄”);returnnull;}}157classAccessDepartment:IDepa157interfaceIFactory{IuserCreateUser();IDepartmentCreateDepartment();}classSqlServerFactory:IFactory{publicIuserCreateUser(){returnnewSqlserverUser();}publicIDepartmentCreateDepartment(){returnnewSqlServerDepartment();}}158interfaceIFactory158158classAccessFactory:IFactory{publicIuserCreateUser(){returnnewAccessUser();}publicIDepartmentCreateDepartment(){returnnewAccessDepartment();}}159classAccessFactory:IFactory159客戶端實現(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客戶端實現(xiàn):160160抽象工廠模式的優(yōu)點易于交換產(chǎn)品系列,由于具體工廠類在一個應(yīng)用中只需要在初始化時出現(xiàn)一次,這就使得改變一個應(yīng)用的具體工廠變得非常容易,它只需要改變具體工廠即可使用不同的產(chǎn)品配置。它讓具體的創(chuàng)建實例過程與客戶端分離,客戶端是通過它們的抽象接口操縱實例,產(chǎn)品的具體類名也被具體工廠的實現(xiàn)分離,不會出現(xiàn)在客戶代碼中。161抽象工廠模式的優(yōu)點易于交換產(chǎn)品系列,由于具體工廠類在一個應(yīng)用161抽象工廠模式
多個抽象產(chǎn)品類,每個抽象產(chǎn)品類可以派生出多個具體產(chǎn)品類。
一個抽象工廠類,可以派生出多個具體工廠類。
每個具體工廠類可以創(chuàng)建多個具體產(chǎn)品類的實例。
162抽象工廠模式 多個抽象產(chǎn)品類,每個抽象產(chǎn)品類可以派生出多個具162比較工廠方法和抽象方法抽象工廠的需求:創(chuàng)建一個產(chǎn)品家族負責(zé)在抽象工廠中創(chuàng)建產(chǎn)品的方法,通常是以“工廠方法”來實現(xiàn)的163比較工廠方法和抽象方法抽象工廠的需求:創(chuàng)建一個產(chǎn)品家族163163FactoryMethod(工廠方法)模式例子:“去快餐廳吃飯”164FactoryMethod(工廠方法)模式例子:“去快餐廳164165void
BuyFood(string
餐館,string食品){
if(餐館=="KFC"){
if(食品=="Chicken")hamburger=newKFCChickenHamburger;
else
if(food=="Fish")hamburger=newKFCFishHamburger;}
else
if(restaurant=="McDonald"){
if(food=="Chicken")hamburger=newMcDonaldChickenHamburger;
else
if(food=="Fish")hamburger=newMcDonaldFishHamburger;}}165voidBuyFood(string餐館,st165FactoryMethod(工廠方法)模式增加一種新的食物呢?166FactoryMethod(工廠方法)模式增加一種新的食物166FactoryMethod(工廠方法)模式傳統(tǒng)設(shè)計的缺點依賴具體167void
BuyFood(string
餐館,string食品){
if(餐館=="KFC"){
if(食品=="Chicken")hamburger=new
KFCChickenHamburger;
else
if(food=="Fish")hamburger=new
KFCFishHamburger;}...FactoryMethod(工廠方法)模式傳統(tǒng)設(shè)計的缺點1167FactoryMethod(工廠方法)模式“Abstractionshouldnotdependupondetails.Detailsshoulddependuponabstractions”168設(shè)計原則5:依賴倒置原則抽象不應(yīng)當(dāng)依賴于細節(jié)細節(jié)應(yīng)當(dāng)依賴于抽象FactoryMethod(工廠方法)模式168設(shè)計原則5168設(shè)計原則:依賴倒置原則為什么說“倒置”傳統(tǒng)的設(shè)計是抽象層依賴具體層傳統(tǒng)的重用,側(cè)重于具體層次的模塊,比如算法、數(shù)據(jù)結(jié)構(gòu)、函數(shù)庫因此軟件的高層模塊依賴低層模塊169傳統(tǒng)的依賴方向設(shè)計原則:依賴倒置原則為什么說“倒置”169傳169設(shè)計原則:依賴倒置原則高層依賴低層的問題抽象層包含的是系統(tǒng)的業(yè)務(wù)邏輯和宏觀的、戰(zhàn)略性的決定,是必然性的體現(xiàn)具體層則含有與實現(xiàn)相關(guān)的算法和邏輯,以及戰(zhàn)術(shù)性的決定,帶有相當(dāng)大的偶然性選擇。具體層經(jīng)常有變動,難免出現(xiàn)錯誤必然依賴偶然,穩(wěn)定依賴變動?170設(shè)計原則:依賴倒置原則高層依賴低層的問題170170設(shè)計原則:依賴倒置原則依賴具體的缺點171設(shè)計原則:依賴倒置原則依賴具體的缺點171171設(shè)計原則:依賴倒置原則依賴抽象抽象一般不會變動這樣代碼不會受易變的具體層影響172設(shè)計原則:依賴倒置原則依賴抽象172172設(shè)計原則:針對接口編程如何做到“依賴倒置”?“Programtoaninterface,notanimplementation”173設(shè)計原則6:針對接口編程要針對接口編程不要針對實現(xiàn)編程設(shè)計原則:針對接口編程如何做到“依賴倒置”?173設(shè)計原則6173設(shè)計原則:針對接口編程“針對接口編程”的一些建議變量、參數(shù)、返回值等應(yīng)聲明為抽象類不要繼承非抽象類不要重載父類的非抽象方法當(dāng)然這些只是建議實際情況要權(quán)衡利弊174設(shè)計原則:針對接口編程“針對接口編程”的一些建議174174FactoryMethod(工廠方法)模式“女媧摶土造人”《風(fēng)俗通》:“俗說天開地辟,未有人民。女媧摶黃土為人?!?75FactoryMethod(工廠方法)模式“女媧摶土造人”175FactoryMethod(工廠方法)模式簡單工廠:根據(jù)傳入的參數(shù),決定創(chuàng)建哪一個產(chǎn)品類對象176Human*
NvWa::CreateHuman(stringname){
if(name
==“ZhangSan") returnnew
ZhangSan;
elseif(name
==“LiSi") returnnew
LiSi;
elseif(name==“WangErMaZi") returnnew
WangErMaZi;}FactoryMethod(工廠方法)模式簡單工廠:根據(jù)傳176FactoryMethod(工廠方法)模式簡單工廠的優(yōu)缺點優(yōu)點:實現(xiàn)了責(zé)任分割利用判斷邏輯,決定實例化哪一個產(chǎn)品類客戶端可以免除直接創(chuàng)建產(chǎn)品類對象的責(zé)任,僅僅使用該產(chǎn)品缺點:沒有完全做到“開-閉”一旦增加新的產(chǎn)品,需要修改工廠的代碼但是客戶代碼不需要修改“我不入地獄誰入地獄”177FactoryMethod(工廠方法)模式簡單工廠的優(yōu)缺點177FactoryMethod(工廠方法)模式“女媧舉繩造人”“女媧摶土為人,劇務(wù),力不暇供,乃引繩于桓泥中,舉以為人?!?78FactoryMethod(工廠方法)模式“女媧舉繩造人”178FactoryMethod(工廠方法)模式簡單工廠的問題所有具體產(chǎn)品對象的創(chuàng)建都放在一個類中,一旦增加新的產(chǎn)品,當(dāng)然工廠類要被修改工廠方法:使用多態(tài)來應(yīng)對提供一個抽象工廠的接口具體工廠分別負責(zé)創(chuàng)建具體產(chǎn)品對象增加新的產(chǎn)品只需要相應(yīng)增加新的具體工廠類179FactoryMethod(工廠方法)模式簡單工廠的問題1179FactoryMethod(工廠方法)模式意圖定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪一個類使一個類的實例化延遲到其子類優(yōu)點封裝了創(chuàng)建具體對象的工作使得客戶代碼“針對接口編程”,保持對變化的“關(guān)閉”180FactoryMethod(工廠方法)模式意圖180180FactoryM
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 幼兒園家長會方案設(shè)計幼兒園家長會活動方案
- 2024-2025新進廠員工安全培訓(xùn)考試試題答案高清版
- 2025年公司安全培訓(xùn)考試試題含完整答案【易錯題】
- 2025版限價房購房合同范本
- 2025年度文具采購合同文具采購合同范本
- 2025試用合同范本2
- 2025建筑涂料施工合同范本
- 2025××科技公司合同管理業(yè)績制度
- 2025年服裝、鞋帽加工機械項目合作計劃書
- 2025年攪拌機租賃合同范本
- YY/T 0655-2024干式化學(xué)分析儀
- 中華民族共同體概論課件專家版2第二講 樹立正確的中華民族歷史觀
- 四年級四年級下冊閱讀理解100篇及答案經(jīng)典
- 中職對口升學(xué)復(fù)習(xí)資料:《汽車機械基礎(chǔ)》試題庫+答案
- 部編版語文五年級下冊第六單元整體教學(xué)設(shè)計教案
- 平面變壓器設(shè)計與仿真
- 合作取得更大的成功辯論稿范文六篇
- 相關(guān)方需求和期望識別評價表
- 西南科技大學(xué)井巷工程課程設(shè)計樣本
- 某化妝品牌案例分析
- 循環(huán)水管道施工組織設(shè)計
評論
0/150
提交評論