【設(shè)計(jì)模式自習(xí)室】適配器模式

前言

《設(shè)計(jì)模式自習(xí)室》系列鸵赖,顧名思義毕贼,本系列文章帶你溫習(xí)常見(jiàn)的設(shè)計(jì)模式温赔。主要內(nèi)容有:

  • 該模式的介紹,包括:
    • 引子鬼癣、意圖(大白話(huà)解釋?zhuān)?/li>
    • 類(lèi)圖陶贼、時(shí)序圖(理論規(guī)范)
  • 該模式的代碼示例:熟悉該模式的代碼長(zhǎng)什么樣子
  • 該模式的優(yōu)缺點(diǎn):模式不是萬(wàn)金油,不可以濫用模式
  • 該模式的實(shí)際使用案例:了解它在哪些重要的源碼中被使用

該系列會(huì)逐步更新于我的博客和公眾號(hào)(博客見(jiàn)文章底部)待秃,也希望各位觀眾老爺能夠關(guān)注我的個(gè)人公眾號(hào):后端技術(shù)漫談拜秧,不會(huì)錯(cuò)過(guò)精彩好看的文章。

系列文章回顧

結(jié)構(gòu)型——適配器模式

引子

當(dāng)你從中國(guó)到國(guó)外旅游時(shí)枉氮,經(jīng)常會(huì)購(gòu)買(mǎi)一個(gè)電源適配器,也就是電源轉(zhuǎn)接頭暖庄,因?yàn)閲?guó)外的插座經(jīng)常無(wú)法適用于國(guó)內(nèi)的插頭嘲恍,這個(gè)電源轉(zhuǎn)接頭就是一個(gè)適配器,也就是下圖中的Adapter雄驹,它讓你的插頭能夠正常的在國(guó)外使用佃牛。

客戶(hù)類(lèi)調(diào)用適配器的方法時(shí)泣特,在適配器類(lèi)的內(nèi)部將調(diào)用適配者類(lèi)的方法带兜,而這個(gè)過(guò)程對(duì)客戶(hù)類(lèi)是透明的平项,客戶(hù)類(lèi)并不直接訪(fǎng)問(wèn)適配者類(lèi)逃顶。

image

定義

適配器模式把一個(gè)類(lèi)的接口變換成客戶(hù)端所期待的另一種接口薪捍,從而使原本因接口不匹配而無(wú)法在一起工作的兩個(gè)類(lèi)能夠在一起工作危融。

適配器模式有類(lèi)的適配器模式和對(duì)象的適配器模式兩種不同的形式陵刹。

1. 類(lèi)適配器

創(chuàng)建新類(lèi)啃洋,繼承源類(lèi)霞怀,同時(shí)還要實(shí)現(xiàn)新接口

class  adapter extends oldClass implements newFunc{}

2. 對(duì)象適配器

創(chuàng)建新類(lèi)的實(shí)例惫东,其中包含舊的類(lèi),并實(shí)現(xiàn)新接口

class adapter implements newFunc { private oldClass oldInstance ;}
  • 類(lèi)適配器使用對(duì)象繼承的方式毙石,是靜態(tài)的定義方式
  • 對(duì)象適配器使用對(duì)象組合的方式廉沮,是動(dòng)態(tài)組合的方式。

類(lèi)圖

如果看不懂UML類(lèi)圖徐矩,可以先粗略瀏覽下該圖滞时,想深入了解的話(huà),可以繼續(xù)谷歌滤灯,深入學(xué)習(xí):

image

適配器模式包含如下角色:

  • Target:目標(biāo)抽象類(lèi):這就是所期待得到的新接口類(lèi)坪稽。
  • Adapter:適配器類(lèi):適配器類(lèi)是本模式的核心曼玩。適配器把源接口轉(zhuǎn)換成目標(biāo)接口。顯然窒百,這一角色不可以是接口黍判,而必須是具體類(lèi)。
  • Adaptee:適配者類(lèi):等待適配的舊類(lèi)
  • Client:客戶(hù)端調(diào)用者

1. 類(lèi)適配器

image

2. 對(duì)象適配器

image

時(shí)序圖

時(shí)序圖(Sequence Diagram)是顯示對(duì)象之間交互的圖篙梢,這些對(duì)象是按時(shí)間順序排列的样悟。時(shí)序圖中顯示的是參與交互的對(duì)象及其對(duì)象之間消息交互的順序。

我們可以大致瀏覽下時(shí)序圖庭猩,如果感興趣的小伙伴可以去深究一下:

image

代碼示例/使用場(chǎng)景舉例

這次我將代碼示例和使用場(chǎng)景兩個(gè)章節(jié)合起來(lái)講,是因?yàn)橛幸粋€(gè)十分典型的Java 源碼可以學(xué)習(xí)

1. Java容器中的Enumeration老接口和Iterator新接口

JDK1.1 之前提供的容器有Arrays,Vector,Stack,Hashtable,Properties,BitSet陈症,其中定義了一種訪(fǎng)問(wèn)群集內(nèi)各元素的標(biāo)準(zhǔn)方式蔼水,稱(chēng)為 Enumeration(列舉器)接口。

JDK1.2 版本中引入了 Iterator接口录肯,新版本的集合對(duì)(HashSet,HashMap,WeakHeahMap,ArrayList,TreeSet,TreeMap, LinkedList)是通過(guò) Iterator 接口訪(fǎng)問(wèn)集合元素趴腋。

這樣,如果將老版本的程序運(yùn)行在新的 Java 編譯器上就會(huì)出錯(cuò)论咏。因?yàn)?List 接口中已經(jīng)沒(méi)有 elements()优炬,而只有 iterator() 了。那么如何將老版本的程序運(yùn)行在新的 Java 編譯器上呢? 如果不加修改厅贪,是肯定不行的蠢护,但是修改要遵循“開(kāi)-閉”原則我們可以用 Java 設(shè)計(jì)模式中的適配器模式解決這個(gè)問(wèn)題。


public class EnumIter implements Iterator {//重點(diǎn)1:配器實(shí)現(xiàn)目標(biāo)接口

   private Enumeration e;//重點(diǎn)2:適配器持有被適配接口(對(duì)象)的引用

   public EnumIter(Enumeration e){
       this.e = e;
   }


   //將對(duì)目標(biāo)對(duì)象的調(diào)用轉(zhuǎn)發(fā)給真正的被適配的對(duì)象
   public boolean hasNext() {
       return e.hasMoreElements();
   }
   public Object next() {
       return e.nextElement();
   }
   public void remove() {

   }
}

NewEnumeration 是一個(gè)適配器類(lèi)养涮,通過(guò)它實(shí)現(xiàn)了從 Iterator 接口到 Enumeration 接口的適配葵硕,這樣我們就可以使用老版本的代碼來(lái)使用新的集合對(duì)象了。

2. JDBC也是一種適配器模式

Sun公司在1996年公開(kāi)了Java語(yǔ)言的數(shù)據(jù)庫(kù)連接工具JDBC贯吓,JDBC使得Java語(yǔ)言程序能夠與數(shù)據(jù)庫(kù)連接懈凹,并使用SQL語(yǔ)言來(lái)查詢(xún)和操作數(shù)據(jù)。JDBC給出一個(gè)客戶(hù)端通用的抽象接口悄谐,每一個(gè)具體數(shù)據(jù)庫(kù)引擎(如SQL Server介评、Oracle、MySQL等)的JDBC驅(qū)動(dòng)軟件都是一個(gè)介于JDBC接口和數(shù)據(jù)庫(kù)引擎接口之間的適配器軟件爬舰。抽象的JDBC接口和各個(gè)數(shù)據(jù)庫(kù)引擎API之間都需要相應(yīng)的適配器軟件们陆,這就是為各個(gè)不同數(shù)據(jù)庫(kù)引擎準(zhǔn)備的驅(qū)動(dòng)程序。

模式優(yōu)缺點(diǎn)

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

  • 將目標(biāo)類(lèi)和適配者類(lèi)解耦情屹,而無(wú)須修改原有代碼棒掠。
  • 對(duì)于客戶(hù)端類(lèi)來(lái)說(shuō)是透明的,而且提高了適配者的復(fù)用性屁商。

類(lèi)適配器模式還具有如下優(yōu)點(diǎn):

由于適配器類(lèi)是適配者類(lèi)的子類(lèi)烟很,因此可以在適配器類(lèi)中置換一些適配者的方法颈墅,使得適配器的靈活性更強(qiáng)。

對(duì)象適配器模式還具有如下優(yōu)點(diǎn):

一個(gè)對(duì)象適配器可以把多個(gè)不同的適配者適配到同一個(gè)目標(biāo)雾袱,也就是說(shuō)恤筛,同一個(gè)適配器可以把適配者類(lèi)和它的子類(lèi)都適配到目標(biāo)接口。

缺點(diǎn)

過(guò)多的使用適配器芹橡,會(huì)讓系統(tǒng)非常零亂毒坛,不易整體進(jìn)行把握。比如林说,明明看到調(diào)用的是A接口煎殷,其實(shí)內(nèi)部被適配成了B接口的實(shí)現(xiàn),一個(gè)系統(tǒng)如果太多出現(xiàn)這種情況腿箩,無(wú)異于一場(chǎng)災(zāi)難豪直。

因此如果不是很有必要,可以不使用適配器珠移,而是直接對(duì)系統(tǒng)進(jìn)行重構(gòu)弓乙。

總結(jié)

建議盡量使用對(duì)象適配器的實(shí)現(xiàn)方式,多用合成/聚合钧惧、少用繼承暇韧。當(dāng)然,具體問(wèn)題具體分析浓瞪,根據(jù)需要來(lái)選用實(shí)現(xiàn)方式懈玻,最適合的才是最好的。

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乾颁,一起剝皮案震驚了整個(gè)濱河市酪刀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钮孵,老刑警劉巖骂倘,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異巴席,居然都是意外死亡历涝,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)漾唉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)荧库,“玉大人,你說(shuō)我怎么就攤上這事赵刑》稚溃” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵般此,是天一觀的道長(zhǎng)蚪战。 經(jīng)常有香客問(wèn)我牵现,道長(zhǎng),這世上最難降的妖魔是什么邀桑? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任瞎疼,我火速辦了婚禮,結(jié)果婚禮上壁畸,老公的妹妹穿的比我還像新娘贼急。我一直安慰自己,他們只是感情好捏萍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布太抓。 她就那樣靜靜地躺著,像睡著了一般令杈。 火紅的嫁衣襯著肌膚如雪走敌。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,708評(píng)論 1 305
  • 那天这揣,我揣著相機(jī)與錄音,去河邊找鬼影斑。 笑死给赞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的矫户。 我是一名探鬼主播片迅,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼皆辽!你這毒婦竟也來(lái)了柑蛇?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤驱闷,失蹤者是張志新(化名)和其女友劉穎耻台,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體空另,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盆耽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扼菠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摄杂。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖循榆,靈堂內(nèi)的尸體忽然破棺而出析恢,到底是詐尸還是另有隱情,我是刑警寧澤秧饮,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布映挂,位于F島的核電站泽篮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏袖肥。R本人自食惡果不足惜咪辱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望椎组。 院中可真熱鬧油狂,春花似錦、人聲如沸寸癌。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蒸苇。三九已至磷蛹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間溪烤,已是汗流浹背味咳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留檬嘀,地道東北人槽驶。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像鸳兽,于是被迫代替她去往敵國(guó)和親掂铐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

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