漫话:如何给女朋友解释什么是适配器模式?
本文經(jīng)授權(quán)轉(zhuǎn)載自微信公眾號(hào):漫話編程
周末窩在家里面打王者榮耀,女朋友在旁邊玩我的電腦,我嫌她播放的綜藝節(jié)目聲音比較大,于是建議她戴耳機(jī)。
適配器模式Adapter Pattern,通常被翻譯成適配器模式,有時(shí)候也叫做包裝模式(wrapper pattern),是GOF 23種設(shè)計(jì)模式之一。主要作用是將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。適配器模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。
《Design Patterns: Elements of Reusable Object-Oriented Software》(《設(shè)計(jì)模式》),由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著(Addison-Wesley,1995)。這幾位作者常被稱為"Gang of Four),簡稱GOF。
GOF中將適配器模式分為類適配器模式和對(duì)象適配器模式。
對(duì)象適配器模式
在這種適配器模式中,適配器容納一個(gè)它包裹的類的實(shí)例。在這種情況下,適配器調(diào)用被包裹對(duì)象的物理實(shí)體。
類適配器模式
這種適配器模式下,適配器繼承自已實(shí)現(xiàn)的類(一般多重繼承)。
二者區(qū)別僅在于適配器角色對(duì)于被適配角色的適配是通過繼承還是組合來實(shí)現(xiàn)的,由于Java中不支持多繼承,而且類適配器模式有破壞封裝之嫌,而且我們也提倡多用組合少用繼承。所以本文主要介紹對(duì)象適配器。
適配器模式用途我們生活中經(jīng)常需要用到插口轉(zhuǎn)換器,比如現(xiàn)在很多手機(jī)都只有一個(gè)插口,這個(gè)口可以直接用來充電和聽音樂。但是前提是我們使用的充電器和耳機(jī)的插口要和這個(gè)設(shè)備適配的。
目前市面上很多手機(jī)的插口都是type-c或者Lightning型號(hào):
但是,我們常用的耳機(jī)型號(hào)卻是2.5mm和3.5mm的圓形接口:
所以,當(dāng)我們想要把自己的3.5mm圓形接口的耳機(jī)插入Lightning或者type-c接口的時(shí)候,就需要一個(gè)轉(zhuǎn)換器:同理,在軟件系統(tǒng)中,常常要將一些"現(xiàn)存的對(duì)象"放到新的環(huán)境中,而新環(huán)境要求的接口是現(xiàn)對(duì)象不能滿足。如以下類似的場(chǎng)景:1、系統(tǒng)需要使用現(xiàn)有的類,而此類的接口不符合系統(tǒng)的需要。
2、想要建立一個(gè)可以重復(fù)使用的類,用于與一些彼此之間沒有太大關(guān)聯(lián)的一些類,包括一些可能在將來引進(jìn)的類一起工作,這些源類不一定有一致的接口。
3、通過接口轉(zhuǎn)換,將一個(gè)類插入另一個(gè)類系中。(比如老虎和飛禽,現(xiàn)在多了一個(gè)飛虎,在不增加實(shí)體的需求下,增加一個(gè)適配器,在里面包容一個(gè)虎對(duì)象,實(shí)現(xiàn)飛的接口。)
適配器模式,就可以解決以上的問題。
適配器模式實(shí)現(xiàn)方式下面我們就使用適配器模式,模擬一種場(chǎng)景:使用一個(gè)安卓的type-c充電器給只支持 Lightning接口的蘋果手機(jī)充電(假設(shè)可以完美支持)。
已知,我們有一個(gè)type-c充電器、一個(gè)Lightning插口的蘋果手機(jī)。無論是type-c還是Lightning,都是一種標(biāo)準(zhǔn),在代碼中,標(biāo)準(zhǔn)即接口。所以我們先定義兩個(gè)接口:
/**?*?Lightning充電接口?*/public?interface?LightningInterface?{????public?void?chargeWithLightning();}/**?*?TypeC充電接口?*/public?interface?TypeCInterface?{????public?void?chargeWithTypeC();}public?interface?LightningInterface?{
????public?void?chargeWithLightning();
}
/**
?*?TypeC充電接口
?*/
public?interface?TypeCInterface?{
????public?void?chargeWithTypeC();
}
接下來定義我們的蘋果手機(jī),他只支持使用 Lightning插口充電:
public?class?IphoneX?{????private?LightningInterface?lightningInterface;????public?IphoneX()?{????}????public?IphoneX(LightningInterface?lightningInterface)?{????????this.lightningInterface?=?lightningInterface;????}????public?void?charge()?{????????System.out.println("開始給我的IphoneX手機(jī)充電...");????????lightningInterface.chargeWithLightning();????????System.out.println("結(jié)束給我的IphoneX手機(jī)充電...");????}????//setter/getter}class?IphoneX?{????private?LightningInterface?lightningInterface;
????public?IphoneX()?{
????}
????public?IphoneX(LightningInterface?lightningInterface)?{
????????this.lightningInterface?=?lightningInterface;
????}
????public?void?charge()?{
????????System.out.println("開始給我的IphoneX手機(jī)充電...");
????????lightningInterface.chargeWithLightning();
????????System.out.println("結(jié)束給我的IphoneX手機(jī)充電...");
????}
????//setter/getter
}
然后再來看看我們的安卓充電器應(yīng)該如何定義:
/**?*?安卓設(shè)備的充電器?*/public?class?AndroidCharger?implements?TypeCInterface?{????@Override????public?void?chargeWithTypeC()?{????????System.out.println("使用Type-C型號(hào)的充電器充電...");????}}public?class?AndroidCharger?implements?TypeCInterface?{
????
????public?void?chargeWithTypeC()?{
????????System.out.println("使用Type-C型號(hào)的充電器充電...");
????}
}
有了安卓充電器和蘋果手機(jī)。接下來,我們就要定義一個(gè)適配器了,希望通過這個(gè)適配器,我們可以實(shí)現(xiàn)使用安卓設(shè)備的充電器給蘋果手機(jī)充電:
public?class?Adapter?implements?LightningInterface?{????private?TypeCInterface?typeCInterface;????public?Adapter()?{????}????public?Adapter(TypeCInterface?typeCInterface)?{????????typeCInterface?=?typeCInterface;????}????@Override????public?void?chargeWithLightning()?{????????typeCInterface.chargeWithTypeC();????}????//setter/getter}class?Adapter?implements?LightningInterface?{????private?TypeCInterface?typeCInterface;
????public?Adapter()?{
????}
????public?Adapter(TypeCInterface?typeCInterface)?{
????????typeCInterface?=?typeCInterface;
????}
????
????public?void?chargeWithLightning()?{
????????typeCInterface.chargeWithTypeC();
????}
????//setter/getter
}
這個(gè)適配器實(shí)現(xiàn)了LightningInterface,并組合了TypeCInterface,當(dāng)外部調(diào)用chargeWithLightning方法的時(shí)候,實(shí)際上調(diào)用的是typeCInterface.chargeWithTypeC方法。
就像電源適配器,他實(shí)現(xiàn)的是一個(gè)Lightning的規(guī)范,自身是一個(gè)Lightning的插頭,但實(shí)際充電的時(shí)候,他是通過typc-c的電源進(jìn)行的,他起到的是一個(gè)中間轉(zhuǎn)換的作用。
接著我們定義客戶端,實(shí)現(xiàn)我們想要的充電功能:
public?class?Main?{????public?static?void?main(String[]?args)?{????????????Adapter?adapter??=?new?Adapter(new?AndroidCharger());????????????IphoneX?iphoneX?=?new?IphoneX();????????????iphoneX.setLightningInterface(adapter);????????????iphoneX.charge();????????}}class?Main?{????public?static?void?main(String[]?args)?{
????????????Adapter?adapter??=?new?Adapter(new?AndroidCharger());
????????????IphoneX?iphoneX?=?new?IphoneX();
????????????iphoneX.setLightningInterface(adapter);
????????????iphoneX.charge();
????????}
}
輸出結(jié)果如下:
開始給我的IphoneX手機(jī)充電...使用Type-C型號(hào)的充電器充電...結(jié)束給我的IphoneX手機(jī)充電...使用Type-C型號(hào)的充電器充電...
結(jié)束給我的IphoneX手機(jī)充電...
上面的例子通過適配器,我們使用一個(gè)安卓的type-c充電器給一個(gè)只支持Lightning接口的蘋果手機(jī)充電。
上面的代碼,就是一個(gè)適配器模式的例子,這個(gè)例子中,共出現(xiàn)了四種角色:
以上四個(gè)角色中,目標(biāo)抽象類(Lightning接口)、適配者類(安卓充電器)、客戶端(蘋果手機(jī))都是原來代碼中就有的,我們完全不需要對(duì)他們進(jìn)行修改。只需要引入一個(gè)適配器(接口轉(zhuǎn)換器)即可。優(yōu)缺點(diǎn)優(yōu)點(diǎn)
適配器模式(對(duì)象適配器模式),是一種組合優(yōu)于集成的思想的實(shí)現(xiàn)。通過使用適配器模式,我們可以最大程度的復(fù)用已有的了類和代碼。他主要有以下有點(diǎn):
將目標(biāo)類和適配者類解耦,通過引入一個(gè)適配器類來重用現(xiàn)有的適配者類,而無須修改原有代碼。
增加了類的透明性和復(fù)用性,將具體的實(shí)現(xiàn)封裝在適配者類中,對(duì)于客戶端類來說是透明的,而且提高了適配者的復(fù)用性。
靈活性和擴(kuò)展性都非常好,通過使用配置文件,可以很方便地更換適配器,也可以在不修改原有代碼的基礎(chǔ)上增加新的適配器類,完全符合“開閉原則”。
缺點(diǎn)
當(dāng)然,適配器模式并不是完美的,過度使用還是會(huì)帶來一些問題的。缺點(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)。
使用場(chǎng)景
關(guān)于適配器模式的使用場(chǎng)景,一般主要是當(dāng)我們需要修改一些正在運(yùn)行著的代碼,并且希望可以復(fù)用原有代碼實(shí)現(xiàn)新的功能的時(shí)候,就要考慮適配器模式。
在Spring框架中,就大量的使用了適配器模式,讀者可以打開自己的IDE,嘗試著以關(guān)鍵字"Adapter"全局搜索下,一定會(huì)有很多的實(shí)際應(yīng)用。
當(dāng)你遇到的問題,和你想用安卓充電器給蘋果手機(jī)充電類似的時(shí)候,就一定要想到適配器模式哦!
這是關(guān)于設(shè)計(jì)模式的第三篇,前兩篇分別是:《漫話:如何給女朋友解釋什么是策略模式?》《漫話:如何給女朋友解釋什么是單例模式?》還想學(xué)習(xí)哪種設(shè)計(jì)模式,歡迎留言哦。
總結(jié)
以上是生活随笔為你收集整理的漫话:如何给女朋友解释什么是适配器模式?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UVA 10142 Australian
- 下一篇: 2019年容器突然火了,到底什么是容器?