設(shè)計(jì)模式-適配器模式

一 概述

定義:適配器模式將某個(gè)類的接口轉(zhuǎn)換成客戶端期望的另一個(gè)接口表示顽聂,主的目的是兼容性讲坎,讓原本因接口不匹配不能一起工作的兩個(gè)類可以協(xié)同工作星岗。其別名為包裝器(Wrapper)牍白。

屬于結(jié)構(gòu)型模式

主要分為三類:類適配器模式益兄、對(duì)象的適配器模式锻梳、接口的適配器模式。

本文定義:

需要被適配的類净捅、接口疑枯、對(duì)象(我們有的),簡(jiǎn)稱src(source)

最終需要的輸出(我們想要的)蛔六,簡(jiǎn)稱dst(destination荆永,即Target)

適配器稱之為Adapter废亭。

一句話描述適配器模式的感覺:src->Adapter->dst,即src以某種形式(三種形式分別對(duì)應(yīng)三種適配器模式)給到Adapter里,最終轉(zhuǎn)化成了dst具钥。

拿我們Android開發(fā)最熟悉的展示列表數(shù)據(jù)的三大控件:ListView豆村,GridView,RecyclerView的Adapter來說骂删,它們?nèi)齻€(gè)控件需要的是View(dst),而我們有的一般是datas(src),所以適配器Adapter就是完成了數(shù)據(jù)源datas 轉(zhuǎn)化成 ItemView的工作掌动。

帶入src->Adapter->dst中,即datas->Adapter->View.

使用場(chǎng)景:

1 系統(tǒng)需要使用現(xiàn)有的類宁玫,而這些類的接口不符合系統(tǒng)的需要坏匪。

2 想要建立一個(gè)可以重復(fù)使用的類,用于與一些彼此之間沒有太大關(guān)聯(lián)的一些類撬统,包括一些可能在將來引進(jìn)的類一起工作适滓。

3 需要一個(gè)統(tǒng)一的輸出接口,而輸入端的類型不可預(yù)知恋追。

二 類適配器模式:

一句話描述:Adapter類凭迹,通過繼承src類,實(shí)現(xiàn)dst 類接口苦囱,完成src->dst的適配嗅绸。

別的文章都用生活中充電器的例子來講解適配器,的確撕彤,這是個(gè)極佳的舉例鱼鸠,本文也不能免俗:

充電器本身相當(dāng)于Adapter,220V交流電相當(dāng)于src羹铅,我們的目dst標(biāo)是5V直流電蚀狰。

UserAdapter不僅實(shí)現(xiàn)了UserInterface接口,同時(shí)還繼承了UserInfo類职员。在實(shí)現(xiàn)接口的getName()和getTelNumber()方法中麻蹋,分別調(diào)用了UserInfo類中的相應(yīng)方法并取得結(jié)果。由此可以滿足需求焊切。在上述定義中扮授,按照UserInterface、UserInfo和UserAdapter在場(chǎng)景中的目的不同专肪,可以具體劃分成如下角色:

UserInterface:目標(biāo)角色——目標(biāo)接口刹勃,系統(tǒng)所期待實(shí)現(xiàn)的目標(biāo);

UserInfo:源角色——當(dāng)前已經(jīng)存在的原有的實(shí)現(xiàn)類嚎尤,即將被適配的類荔仁;

UserAdapter:適配器角色——將原有實(shí)現(xiàn)裝換為目標(biāo)接口的實(shí)現(xiàn)。

簡(jiǎn)單點(diǎn)說,適配器模式是指:定義一個(gè)類咕晋,將一個(gè)已經(jīng)存在的類雹拄,轉(zhuǎn)換成目標(biāo)接口所期望的行為形式。

在具體的實(shí)現(xiàn)過程中掌呜,又可以基于其實(shí)現(xiàn)層次是類層次還是對(duì)象層次滓玖,將其分為類適配器和對(duì)象適配器。如上所寫的是類適配器质蕉。

對(duì)象適配器使用組合代替繼承势篡,將源角色視為適配器角色的屬性:

總體而言:適配器模式是指定義一個(gè)適配器類,將一個(gè)已經(jīng)存在的類模暗,轉(zhuǎn)換成目標(biāo)接口所期望的行為形式禁悠。同時(shí),一般來說兑宇,基于更多的推薦使用組合而不是繼承碍侦,因此,對(duì)象適配器可能使用更多隶糕。

類適配器和對(duì)象適配器的選擇

從實(shí)現(xiàn)上:類適配器使用對(duì)象繼承的方式瓷产,屬于靜態(tài)的定義方式。對(duì)象適配器使用對(duì)象組合的方式枚驻,屬于動(dòng)態(tài)組合的方式濒旦;

從工作模式上:類適配器直接繼承了 Adaptee,使得適配器不能和 Adaptee 的子類一起工作再登。對(duì)象適配器允許一個(gè) Adapter 和多個(gè) Adaptee尔邓,包括 Adaptee 和它所有的子類一起工作;

從定義角度:類適配器可以重定義 Adaptee 的部分行為锉矢,相當(dāng)于子類覆蓋父類的部分實(shí)現(xiàn)方法梯嗽。對(duì)象適配器要重定義 Adaptee 很困難;

從開發(fā)角度:類適配器僅僅引入了一個(gè)對(duì)象沈撞,并不需要額外的引用來間接得到 Adaptee慷荔。對(duì)象適配器需要額外的引用來間接得到 Adaptee。

總的來說缠俺,建議使用對(duì)象適配器方式。

適配器模式使用注意事項(xiàng)

充當(dāng)適配器角色的類就是:實(shí)現(xiàn)已有接口的抽象類贷岸;

為什么要用抽象類壹士?此類是不要被實(shí)例化的。而只充當(dāng)適配器的角色偿警,也就為其子類提供了一個(gè)共同的接口躏救,但其子類又可以將精力只集中在其感興趣的地方。

適配器模式中被適配的接口 Adaptee 和適配成為的接口 Target 是沒有關(guān)聯(lián)的,Adaptee 和 Target 中的方法既可以是相同的盒使,也可以是不同的崩掘。

適配器在適配的時(shí)候,可以適配多個(gè) Apaptee少办,也就是說實(shí)現(xiàn)某個(gè)新的 Target 的功能的時(shí)候苞慢,需要調(diào)用多個(gè)模塊的功能,適配多個(gè)模塊的功能才能滿足新接口的要求英妓。

適配器有一個(gè)潛在的問題挽放,就是被適配的對(duì)象不再兼容 Adaptee 的接口,因?yàn)檫m配器只是實(shí)現(xiàn)了 Target 的接口蔓纠。這導(dǎo)致并不是所有 Adaptee 對(duì)象可以被使用的地方都能是使用適配器辑畦,雙向適配器解決了這個(gè)問題。

優(yōu)點(diǎn)

適配器模式也是一種包裝模式腿倚,它與裝飾模式同樣具有包裝的功能纯出,此外,對(duì)象適配器模式還具有委托的意思敷燎≡蒹荩總的來說,適配器模式屬于補(bǔ)償模式懈叹,專用來在系統(tǒng)后期擴(kuò)展乖杠、修改時(shí)使用。

缺點(diǎn)

過多的使用適配器澄成,會(huì)讓系統(tǒng)非常零亂胧洒,不易整體進(jìn)行把握。比如墨状,明明看到調(diào)用的是 A 接口卫漫,其實(shí)內(nèi)部被適配成了 B 接口的實(shí)現(xiàn),一個(gè)系統(tǒng)如果太多出現(xiàn)這種情況肾砂,無異于一場(chǎng)災(zāi)難列赎。因此如果不是很有必要,可以不使用適配器镐确,而是直接對(duì)系統(tǒng)進(jìn)行重構(gòu)包吝。

適配器模式應(yīng)用場(chǎng)景

在軟件開發(fā)中,也就是系統(tǒng)的數(shù)據(jù)和行為都正確源葫,但接口不相符時(shí)诗越,我們應(yīng)該考慮用適配器,目的是使控制范圍之外的一個(gè)原有對(duì)象與某個(gè)接口匹配息堂。適配器模式主要應(yīng)用于希望復(fù)用一些現(xiàn)存的類嚷狞,但是接口又與復(fù)用環(huán)境要求不一致的情況块促。比如在需要對(duì)早期代碼復(fù)用一些功能等應(yīng)用上很有實(shí)際價(jià)值。適用場(chǎng)景大致包含三類:

1床未、已經(jīng)存在的類的接口不符合我們的需求竭翠;

2、創(chuàng)建一個(gè)可以復(fù)用的類薇搁,使得該類可以與其他不相關(guān)的類或不可預(yù)見的類(即那些接口可能不一定兼容的類)協(xié)同工作斋扰;

3、在不對(duì)每一個(gè)都進(jìn)行子類化以匹配它們的接口的情況下只酥,使用一些已經(jīng)存在的子類褥实。

Java I/O 庫(kù)大量使用了適配器模式,例如 ByteArrayInputStream 是一個(gè)適配器類裂允,它繼承了 InputStream 的接口损离,并且封裝了一個(gè) byte 數(shù)組。換言之绝编,它將一個(gè) byte 數(shù)組的接口適配成 InputStream 流處理器的接口僻澎。

我們知道 Java 語(yǔ)言支持四種類型:Java 接口,Java 類十饥,Java 數(shù)組窟勃,原始類型(即 int,float 等)。前三種是引用類型逗堵,類和數(shù)組的實(shí)例是對(duì)象秉氧,原始類型的值不是對(duì)象。也即蜒秤,Java 語(yǔ)言的數(shù)組是像所有的其他對(duì)象一樣的對(duì)象绅络,而不管數(shù)組中所存儲(chǔ)的元素類型是什么列牺。這樣一來的話,ByteArrayInputStream 就符合適配器模式的描述作喘,是一個(gè)對(duì)象形式的適配器類灭袁。FileInputStream 是一個(gè)適配器類尸红。在 FileInputStream 繼承了 InputStrem 類型绩郎,同時(shí)持有一個(gè)對(duì) FileDiscriptor 的引用蔼水。這是將一個(gè) FileDiscriptor 對(duì)象適配成 InputStrem 類型的對(duì)象形式的適配器模式。

同樣地女揭,在 OutputStream 類型中蚤假,所有的原始流處理器都是適配器類。ByteArrayOutputStream 繼承了 OutputStream 類型吧兔,同時(shí)持有一個(gè)對(duì) byte 數(shù)組的引用勤哗。它一個(gè) byte 數(shù)組的接口適配成 OutputString 類型的接口,因此也是一個(gè)對(duì)象形式的適配器模式的應(yīng)用掩驱。

FileOutputStream 繼承了 OutputStream 類型,同時(shí)持有一個(gè)對(duì) FileDiscriptor 對(duì)象的引用。這是一個(gè)將 FileDiscriptor 接口適配成 OutputStream 接口形式的對(duì)象型適配器模式欧穴。

Reader 類型的原始流處理器都是適配器模式的應(yīng)用民逼。StringReader 是一個(gè)適配器類,StringReader 類繼承了 Reader 類型涮帘,持有一個(gè)對(duì) String 對(duì)象的引用拼苍。它將 String 的接口適配成 Reader 類型的接口。


Spring 中使用適配器模式的典型應(yīng)用

在 Spring 的 AOP 里通過使用的 Advice(通知)來增強(qiáng)被代理類的功能调缨。Spring 實(shí)現(xiàn)這一 AOP 功能的原理就使用代理模式(1疮鲫、JDK 動(dòng)態(tài)代理。2弦叶、CGLib 字節(jié)碼生成技術(shù)代理俊犯。)對(duì)類進(jìn)行方法級(jí)別的切面增強(qiáng),即伤哺,生成被代理類的代理類燕侠,并在代理類的方法前,設(shè)置攔截器立莉,通過執(zhí)行攔截器中的內(nèi)容增強(qiáng)了代理方法的功能绢彤,實(shí)現(xiàn)的面向切面編程。

Advice(通知)的類型有:BeforeAdvice蜓耻、AfterReturningAdvice茫舶、ThrowSadvice 等。每個(gè)類型 Advice(通知)都有對(duì)應(yīng)的攔截器刹淌,MethodBeforeAdviceInterceptor饶氏、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor芦鳍。Spring 需要將每個(gè) Advice(通知)都封裝成對(duì)應(yīng)的攔截器類型嚷往,返回給容器,所以需要使用適配器模式對(duì) Advice 進(jìn)行轉(zhuǎn)換柠衅。


http://www.ibm.com/developerworks/cn/java/j-lo-adapter-pattern/index.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末皮仁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子菲宴,更是在濱河造成了極大的恐慌贷祈,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件喝峦,死亡現(xiàn)場(chǎng)離奇詭異势誊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)谣蠢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門粟耻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來查近,“玉大人,你說我怎么就攤上這事挤忙∷” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵册烈,是天一觀的道長(zhǎng)戈泼。 經(jīng)常有香客問我,道長(zhǎng)赏僧,這世上最難降的妖魔是什么大猛? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮淀零,結(jié)果婚禮上挽绩,老公的妹妹穿的比我還像新娘。我一直安慰自己窑滞,他們只是感情好琼牧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著哀卫,像睡著了一般巨坊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上此改,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天趾撵,我揣著相機(jī)與錄音,去河邊找鬼共啃。 笑死占调,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的移剪。 我是一名探鬼主播究珊,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼纵苛!你這毒婦竟也來了剿涮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤攻人,失蹤者是張志新(化名)和其女友劉穎取试,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怀吻,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瞬浓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蓬坡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猿棉。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡磅叛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出铺根,到底是詐尸還是另有隱情宪躯,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布位迂,位于F島的核電站,受9級(jí)特大地震影響详瑞,放射性物質(zhì)發(fā)生泄漏掂林。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一坝橡、第九天 我趴在偏房一處隱蔽的房頂上張望泻帮。 院中可真熱鬧,春花似錦计寇、人聲如沸锣杂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)元莫。三九已至,卻和暖如春蝶押,著一層夾襖步出監(jiān)牢的瞬間踱蠢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工棋电, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茎截,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓赶盔,卻偏偏與公主長(zhǎng)得像企锌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子于未,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容