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

下載本文檔

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

文檔簡介

TheAdapter

Pattern

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

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

publicinterfaceIterator{publicbooleanhasNext();publicObjectnext();publicvoidremove();}枚舉器和迭代器之間非常相似,但有個方法不同。remove方法現(xiàn)在,我們面對了有枚舉器的接口的庫函數(shù),如何讓客戶使用迭代器,我們需要適配器??蛻簦吭矗哼m配器?設(shè)計適配器ClientIteratorRequest()EnumerationExistingRequest()EnumeratinIteratorAdapterRequest()adaptee代碼publicclassEnumerationIteratorimplementsIterator{Enumerationenum;publicEnumerationIterator(Enumerationenum){this.enum=enum;}publicbooleanhasNext(){returnenum.hasMoreElements();}publicObjectnext(){returnenum.nextElement();}publicvoidremove(){thrownewException():}}問題如果現(xiàn)在面對使用了枚舉器接口的客戶代碼,而庫函數(shù)使用了迭代器,如何實現(xiàn)?適配器模式VS裝飾者模式相似點:都是包裝源。不同點:使用適配器的原因是因為接口不匹配;而使用裝飾模式是因為功能有欠缺,但不改變接口。這兩個在概念上還是不一樣的。

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

Decoratorenhancesanotherobjectwithoutchanginginterface利用適配器模式指方為圓 中國古代有趙高指鹿為馬的故事。鹿與馬有很多相似之處,沒見過的人本就分辨不清,指一指可能沒什么大不了的。指方為圓是否太過?非也。本例就是要指方為圓,需要的只是適配器模式這個魔術(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;} 還記得中學的數(shù)學的話,應(yīng)該可以看出,我們的指方為圓系統(tǒng)其實還是有道理的。它接受一個正方體,返還此正方體的內(nèi)切球,也就是能放進此正方體的最大的球。 問題如何實現(xiàn)指圓為方。畫出類圖,給出源碼。請做一個小貓(kittie)的實類,并實現(xiàn)miao(),catchRat(),run(),sleep()等方法。再做一個小狗(doggie)的接口,要求有wao(),fetchBall(),run(),sleep()等方法?,F(xiàn)在你的女朋友想要一只小狗,可是你只找到的一只小貓。請用適配器模式把小貓“適配成”小狗,讓你的女(男)朋友滿意。(提示:量力而為。)編寫一個測試主類,測試你的程序GoF’sFacadePatternMakeitsimplerDefinesahigher-levelinterfacethatmakesthesubsystemeasiertouse外觀模式Provideaunifiedinterfacetoasetofinterfacesinasubsystem.Fa?adedefinesahigher-levelinterfacethatmakesthesubsystemeasiertouse.”為一個子系統(tǒng)的一批接口提供一個統(tǒng)一標準的接口,F(xiàn)acade定義更高層次的接口,使得子系統(tǒng)更容易使用。目的provideunifiedinterfacetoasetofinterfaces為一系列接口集提供統(tǒng)一的接口makessubsystemeasiertouse使得子系統(tǒng)易用作用minimizedependenciesbetweensubsystems降低子系統(tǒng)的依賴性tiestogetherclassesthatprovidesubsystemfunctionalitywithouttotallyhidingclasses將類緊密聯(lián)系在一起提供子系統(tǒng)的功能,并不完全掩藏類。適用性providesimpleinterfacetocomplexsubsystem為復雜子系統(tǒng)提高簡單接口helpdecouplesubsyst

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論