深入淺出設(shè)計(jì)模式之適配器模式_第1頁(yè)
深入淺出設(shè)計(jì)模式之適配器模式_第2頁(yè)
深入淺出設(shè)計(jì)模式之適配器模式_第3頁(yè)
深入淺出設(shè)計(jì)模式之適配器模式_第4頁(yè)
深入淺出設(shè)計(jì)模式之適配器模式_第5頁(yè)
已閱讀5頁(yè),還剩64頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

TheAdapter

Pattern

(結(jié)構(gòu)模式之適配器模式)本章主要內(nèi)容現(xiàn)實(shí)生活中的適配器面向?qū)ο蟮倪m配器適配器的例子適配器模式解析適配器模式概念對(duì)象適配器和類(lèi)適配器Java的迭代器裝飾者和適配器模式現(xiàn)實(shí)生活中的適配器電壓適配當(dāng)把美國(guó)的電器拿回中國(guó)大陸去用的時(shí)候,就面臨電壓不同的問(wèn)題。美國(guó)的生活用電壓是110伏,而中國(guó)的電壓是220伏。怎么辦?如果要在中國(guó)大陸使用在美國(guó)使用的電器,就必須有一個(gè)能把220伏電壓轉(zhuǎn)換成110伏電壓的變壓器?,F(xiàn)實(shí)生活中的適配器請(qǐng)大家舉例鼠標(biāo)的串口和usb口之間的轉(zhuǎn)化面向?qū)ο筌浖到y(tǒng)的適配問(wèn)題假設(shè)我們已經(jīng)有一個(gè)軟件系統(tǒng),原來(lái)使用了一個(gè)第三方類(lèi)庫(kù)A?,F(xiàn)在有一個(gè)新的第三方類(lèi)庫(kù)B,其功能等各方面都更加強(qiáng)大。我們希望用B來(lái)替換A,以改善我們的系統(tǒng)。但是B的接口與A不一樣。那則么辦呢?辦法之一ASystemBNewSystem辦法之一BNewSystemBAdapter辦法之二ASystemBAdapter第二種方案的優(yōu)點(diǎn)System不需要修改代碼不需要修改代碼新代碼辦法之三B’SystemB適配器的例子簡(jiǎn)化的鴨子接口和類(lèi)publicinterfaceDuck{ publicvoidquack(); publicvoidfly();}鴨子接口Duck,定義了鴨子具有“鳴叫”和“飛行”方法MallardDuck類(lèi)publicclassMallardDuckimplementsDuck{ publicvoidquack(){ System.out.println("嘎嘎嘎..."); } publicvoidfly(){ System.out.println("我在飛哦!"); }}MallardDuck類(lèi)簡(jiǎn)單地實(shí)現(xiàn)了Duck接口?,F(xiàn)在有一種新家伙publicinterfaceTurkey{ publicvoidgobble(); publicvoidfly();}WildTurkeypublicclassWildTurkeyimplementsTurkey{ publicvoidgobble(){ System.out.println("咕咕咕..."); } publicvoidfly(){ System.out.println("我在飛,不過(guò)飛不遠(yuǎn)。"); }}我們?cè)瓉?lái)有一個(gè)程序使用鴨子對(duì)象,現(xiàn)在想讓它使用火雞對(duì)象,但是火雞與鴨子的接口不同,不能直接使用。寫(xiě)一個(gè)火雞適配器,讓火雞看起來(lái)像鴨子火雞適配器publicclassTurkeyAdapterimplementsDuck{ Turkeyturkey; publicTurkeyAdapter(Turkeyturkey){ this.turkey=turkey; } publicvoidquack(){ turkey.gobble(); } publicvoidfly(){ for(inti=0;i<5;i++){ turkey.fly(); } }}火雞適配器包裝了一個(gè)火雞對(duì)象,同時(shí)實(shí)現(xiàn)了鴨子接口。這樣就可以像使用鴨子一樣使用火雞了。使用適配器publicclassDuckTestDrive{ publicstaticvoidmain(String[]args){ MallardDuckduck=newMallardDuck(); WildTurkeyturkey=newWildTurkey(); DuckturkeyAdapter=newTurkeyAdapter(turkey); System.out.println("火雞說(shuō)..."); turkey.gobble(); turkey.fly(); System.out.println("\n鴨子說(shuō)..."); testDuck(duck); System.out.println("\n火雞適配器說(shuō)..."); testDuck(turkeyAdapter); } staticvoidtestDuck(Duckduck){ duck.quack(); duck.fly(); }}需要使用鴨子對(duì)象在需要鴨子對(duì)象的地方使用了火雞適配器對(duì)象,

火雞適配器對(duì)象包裝了一個(gè)火雞對(duì)象,所以實(shí)際使用的是火雞對(duì)象。適配器模式詳解被適配者火雞接口客戶(hù)要使用鴨子對(duì)象的程序適配器把火雞裝扮成鴨子目標(biāo)接口:鴨子接口兩者無(wú)耦合彼此不必知道對(duì)方的存在兩者無(wú)耦合彼此不必知道對(duì)方的存在適配器涉及的幾個(gè)概念客戶(hù)(client):使用適配器的用戶(hù)目標(biāo)接口(targetinter):客戶(hù)和適配器之間交互的接口適配器(adapter):客戶(hù)和源之間的中介被適配者接口(adapteeinter):適配器和被適配者(源)之間的接口。被適配者(源)adaptee:試試看現(xiàn)在,如果希望把鴨子包裝成火雞該怎么做?寫(xiě)出你的代碼DuckAdapterDuckAdapter參考答案importjava.util.Random;publicclassDuckAdapterimplementsTurkey{ Duckduck; Randomrand; publicDuckAdapter(Duckduck){ this.duck=duck; rand=newRandom(); } publicvoidgobble(){ duck.quack(); } publicvoidfly(){ if(rand.nextInt(5)==0){ duck.fly(); } }}適配器模式“Converttheinterfaceofaclassintoanotherinterfacethattheclientsexpect.Adapterletsclassesworktogetherthatcouldnototherwisebecauseofincompatibleinterfaces”適配器將一個(gè)類(lèi)的接口轉(zhuǎn)化為客戶(hù)期望的接口類(lèi)型,可以讓一個(gè)類(lèi)與其接口不兼容的類(lèi)進(jìn)行交互。Adapter模式定義將一個(gè)類(lèi)的接口轉(zhuǎn)換成客戶(hù)端所期望的另一種接口,從而使原本因接口不匹配而無(wú)法在一起工作的兩個(gè)類(lèi)能夠在一起工作。別名包裝器WrapperClientTargetRequest()AdapteeExistingRequest()AdapterRequest()adapteeAdapter模式動(dòng)機(jī)有時(shí),為復(fù)用而設(shè)計(jì)的工具箱類(lèi)不能夠被復(fù)用的原因僅僅是因?yàn)樗慕涌谂c專(zhuān)業(yè)應(yīng)用領(lǐng)域所需要的接口不匹配。我們可以改變工具箱類(lèi)使它兼容專(zhuān)業(yè)領(lǐng)域中的類(lèi)的接口,但前提是必須有這個(gè)工具箱的源代碼。然而即使我們得到了這些源代碼,修改工具箱也是沒(méi)有什么意義的;因?yàn)椴粦?yīng)該僅僅為了實(shí)現(xiàn)一個(gè)應(yīng)用,工具箱就不得不采用一些與特定領(lǐng)域相關(guān)的接口。Adapter模式動(dòng)機(jī)(續(xù))我們可以不用上面的方法,而定義一個(gè)適配器類(lèi),由它來(lái)適配工具箱的接口和專(zhuān)業(yè)應(yīng)用的接口。我們可以用兩種方法做這件事:1)繼承專(zhuān)業(yè)應(yīng)用類(lèi)的接口和工具箱類(lèi)的實(shí)現(xiàn)。這種方法對(duì)應(yīng)Adapter模式的類(lèi)版本(多繼承)2)將一個(gè)工具箱類(lèi)的實(shí)例作為適配器類(lèi)的組成部分,并且使用工具箱的接口實(shí)現(xiàn)適配器類(lèi)。這種方法對(duì)應(yīng)Adapter模式的對(duì)象版本。Adapter模式適用性以下情況使用Adapter模式你想使用一個(gè)已經(jīng)存在的類(lèi),而它的接口不符合你的需求。你想創(chuàng)建一個(gè)可以復(fù)用的類(lèi),該類(lèi)可以與其他不相關(guān)的類(lèi)或不可預(yù)見(jiàn)的類(lèi)(即那些接口可能不一定兼容的類(lèi))協(xié)同工作。(僅適用于對(duì)象Adapter)你想使用一些已經(jīng)存在的子類(lèi),但是不可能對(duì)每一個(gè)都進(jìn)行子類(lèi)化以匹配它們的接口。對(duì)象適配器可以適配它的父類(lèi)接口。基于類(lèi)的Adapter模式基于類(lèi)的Adapter模式的一般結(jié)構(gòu)如下:Adaptee類(lèi)為Adapter的父類(lèi),Adaptee類(lèi)為適配源,適配目標(biāo)(接口)也是Adapter的父類(lèi);基于類(lèi)的Adapter模式比較適合應(yīng)用于Adapter想修改Adaptee的部分方法的情況。類(lèi)適配器ClientTargetRequest()AdapteeExistingRequest()AdapterRequest()adaptee1.采用了多繼承來(lái)實(shí)現(xiàn),java不支持多繼承UML系統(tǒng)建模與分析設(shè)計(jì)基于對(duì)象的Adapter模式基于對(duì)象的Adapter模式的一般結(jié)構(gòu)如下:Adaptee類(lèi)對(duì)象為Adapter所依賴(lài),適配目標(biāo)(接口)是Adapter的父類(lèi);基于對(duì)象的Adapter模式比較適合應(yīng)用于Adapter想為Adaptee添加新的方法的情況。但在Adaptee類(lèi)的方法與Adapter類(lèi)的方法不同名而實(shí)現(xiàn)相同功能的情況下,我們一般也使用基于對(duì)象的Adapter模式,Adapter模式效果(類(lèi)適配器和對(duì)象適配器有不同的權(quán)衡)類(lèi)適配器用一個(gè)具體的Adapter類(lèi)對(duì)Adaptee和Target進(jìn)行匹配。結(jié)果是當(dāng)我們想要匹配一個(gè)類(lèi)以及所有它的子類(lèi)時(shí),類(lèi)Adapter將不能勝任工作。使得Adapter可以重定義Adaptee的部分行為,因?yàn)锳dapter是Adaptee的一個(gè)子類(lèi)。僅僅引入了一個(gè)對(duì)象,并不需要額外的指針以間接得到adaptee。Adapter模式效果(類(lèi)適配器和對(duì)象適配器有不同的權(quán)衡)對(duì)象適配器則允許一個(gè)Adapter與多個(gè)Adaptee—即Adaptee本身以及它的所有子類(lèi)(如果有子類(lèi)的話)同時(shí)工作。Adapter也可以一次給所有的Adaptee添加功能。使得重定義Adaptee的行為比較困難。這就需要生成Adaptee的子類(lèi)并且使得Adapter引用這個(gè)子類(lèi)而不是引用Adaptee本身。Java中的迭代器早期的Java中有枚舉器,Enumeration,可以逐個(gè)遍歷集合中的每一個(gè)元素,而不需要知道,集合中元素的結(jié)構(gòu)。publicinterfaceEnumeration{publicbooleanhasMoreElements();publicObjectnextElements();}迭代器Sun公司更新了接口,采用Iterator(迭代器)接口,和枚舉器非常相似,但擴(kuò)展了功能。

publicinterfaceIterator{publicbooleanhasNext();publicObjectnext();publicvoidremove();}枚舉器和迭代器之間非常相似,但有個(gè)方法不同。remove方法現(xiàn)在,我們面對(duì)了有枚舉器的接口的庫(kù)函數(shù),如何讓客戶(hù)使用迭代器,我們需要適配器。客戶(hù)?源:適配器?設(shè)計(jì)適配器ClientIteratorRequest()EnumerationExistingRequest()EnumeratinIteratorAdapterRequest()adaptee代碼publicclassEnumerationIteratorimplementsIterator{Enumerationenum;publicEnumerationIterator(Enumerationenum){this.enum=enum;}publicbooleanhasNext(){returnenum.hasMoreElements();}publicObjectnext(){returnenum.nextElement();}publicvoidremove(){thrownewException():}}問(wèn)題如果現(xiàn)在面對(duì)使用了枚舉器接口的客戶(hù)代碼,而庫(kù)函數(shù)使用了迭代器,如何實(shí)現(xiàn)?適配器模式VS裝飾者模式相似點(diǎn):都是包裝源。不同點(diǎn):使用適配器的原因是因?yàn)榻涌诓黄ヅ?;而使用裝飾模式是因?yàn)楣δ苡星啡保桓淖兘涌?。這兩個(gè)在概念上還是不一樣的。

裝飾者模式就是為原有對(duì)象新增加一個(gè)功能,新的裝飾者對(duì)象>=原有對(duì)象.

Decoratorenhancesanotherobjectwithoutchanginginterface利用適配器模式指方為圓 中國(guó)古代有趙高指鹿為馬的故事。鹿與馬有很多相似之處,沒(méi)見(jiàn)過(guò)的人本就分辨不清,指一指可能沒(méi)什么大不了的。指方為圓是否太過(guò)?非也。本例就是要指方為圓,需要的只是適配器模式這個(gè)魔術(shù)手指(MagicFinger)。 publicclassCube{publicCube(doublewidth){this.width=width;}publicdoublecalculateVolume(){returnwidth*width*width;}publicdoublecalculateFaceArea(){returnwidth*width;}publicdoublegetWidth(){returnthis.width;}publicvoidsetWidth(doublewidth){this.width=width;}privatedoublewidth;}publicinterfaceBallIF{doublecalculateArea();doublecalculateVolume();doublegetRadius();voidsetRadius(doubleradius);}publicclassMagicFingerimplementsBallIF{publicMagicFinger(Cubeadaptee){super();this.adaptee=adaptee;radius=adaptee.getWidth();}publicdoublecalculateArea(){returnPI*4.0D*(radius*radius);}publicdoublecalculateVolume(){returnPI*4.0D/3.0D*(radius*radius*radius);} publicdoublegetRadius(){returnradius;}publicvoidsetRadius(doubleradius){this.radius=radius;}privatedoubleradius=0;privatestaticfinaldoublePI=3.14D;privateCubeadaptee;} 還記得中學(xué)的數(shù)學(xué)的話,應(yīng)該可以看出,我們的指方為圓系統(tǒng)其實(shí)還是有道理的。它接受一個(gè)正方體,返還此正方體的內(nèi)切球,也就是能放進(jìn)此正方體的最大的球。 問(wèn)題如何實(shí)現(xiàn)指圓為方。畫(huà)出類(lèi)圖,給出源碼。請(qǐng)做一個(gè)小貓(kittie)的實(shí)類(lèi),并實(shí)現(xiàn)miao(),catchRat(),run(),sleep()等方法。再做一個(gè)小狗(doggie)的接口,要求有wao(),fetchBall(),run(),sleep()等方法。現(xiàn)在你的女朋友想要一只小狗,可是你只找到的一只小貓。請(qǐng)用適配器模式把小貓“適配成”小狗,讓你的女(男)朋友滿意。(提示:量力而為。)編寫(xiě)一個(gè)測(cè)試主類(lèi),測(cè)試你的程序GoF’sFacadePatternMakeitsimplerDefinesahigher-levelinterfacethatmakesthesubsystemeasiertouse外觀模式Provideaunifiedinterfacetoasetofinterfacesinasubsystem.Fa?adedefinesahigher-levelinterfacethatmakesthesubsystemeasiertouse.”為一個(gè)子系統(tǒng)的一批接口提供一個(gè)統(tǒng)一標(biāo)準(zhǔn)的接口,F(xiàn)acade定義更高層次的接口,使得子系統(tǒng)更容易使用。目的provideunifiedinterfacetoasetofinterfaces為一系列接口集提供統(tǒng)一的接口makessubsystemeasiertouse使得子系統(tǒng)易用作用minimizedependenciesbetweensubsystems降低子系統(tǒng)的依賴(lài)性tiestogetherclassesthatprovidesubsystemfunctionalitywithouttotallyhidingclasses將類(lèi)緊密聯(lián)系在一起提供子系統(tǒng)的功能,并不完全掩藏類(lèi)。適用性providesimpleinterfacetocomplexsubsystem為復(fù)雜子系統(tǒng)提高簡(jiǎn)單接口helpdecouplesubsyst

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 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ì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論