前言:
適配器模式(Adapter Pattern)是作為兩個(gè)不兼容的接口之間的橋梁。這種類型的設(shè)計(jì)模式屬于結(jié)構(gòu)型模式,它結(jié)合了兩個(gè)獨(dú)立接口的功能。
適配器模式通過定義一個(gè)新的接口(對(duì)要實(shí)現(xiàn)的功能加以抽象),和一個(gè)實(shí)現(xiàn)該接口的Adapter(適配器)類來透明地調(diào)用外部組件。這樣替換外部組件時(shí),最多只要修改幾個(gè)Adapter類就可以了,其他源代碼都不會(huì)受到影響。
以手機(jī)為例子,每一種機(jī)型都自帶有充電器,有一天自帶充電器壞了,而且市場(chǎng)沒有這類型充電器可買了,怎么辦?萬能充電器就可以解決,這個(gè)萬能充電器就是適配器。
適配器模式有兩種形式,一種是類的適配,另一種自然就是對(duì)象的適配。
介紹:
1、意圖:將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。適配器模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。
2、主要解決:主要解決在軟件系統(tǒng)中,常常要將一些"現(xiàn)存的對(duì)象"放到新的環(huán)境中,而新環(huán)境要求的接口是現(xiàn)對(duì)象不能滿足的。
3、何時(shí)使用:①系統(tǒng)需要使用現(xiàn)有的類,而此類的接口不符合系統(tǒng)的需要。 ②想要建立一個(gè)可以重復(fù)使用的類,用于與一些彼此之間沒有太大關(guān)聯(lián)的一些類,包括一些可能在將來引進(jìn)的類一起工作,這些源類不一定有一致的接口。 ③通過接口轉(zhuǎn)換,將一個(gè)類插入另一個(gè)類系中。(比如老虎和飛禽,現(xiàn)在多了一個(gè)飛虎,在不增加實(shí)體的需求下,增加一個(gè)適配器,在里面包容一個(gè)虎對(duì)象,實(shí)現(xiàn)飛的接口。)
4、如何解決:繼承或依賴(推薦)。
5、關(guān)鍵代碼:適配器繼承或依賴已有的對(duì)象,實(shí)現(xiàn)想要的目標(biāo)接口。
6、優(yōu)點(diǎn): 1、可以讓任何兩個(gè)沒有關(guān)聯(lián)的類一起運(yùn)行。 2、提高了類的復(fù)用。 3、增加了類的透明度。 4、靈活性好。
7、缺點(diǎn): 1、過多地使用適配器,會(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)。 2.由于 JAVA 至多繼承一個(gè)類,所以至多只能適配一個(gè)適配者類,而且目標(biāo)類必須是抽象類。
類的適配:
這種適配器由三種角色組成:
1、目標(biāo)(Target)角色:這就是所期待得到的接口。注意:由于這里討論的是類適配器模式,因此目標(biāo)不可以是類。
2、源(Adapee)角色:現(xiàn)在需要適配的接口。
3、適配器(Adaper)角色:適配器類是本模式的核心。適配器把源接口轉(zhuǎn)換成目標(biāo)接口。顯然,這一角色不可以是接口,而必須是具體類。
對(duì)象的適配:
對(duì)象的適配依賴于對(duì)象的組合,而不是類適配中的繼承。
示例:
1、類適配器

故事情景:手機(jī)充電用手機(jī)充電器充電,耳機(jī)用耳機(jī)充電器充電,現(xiàn)在要實(shí)現(xiàn)給手機(jī)充電的同時(shí)也能給耳機(jī)充電。
首先來一個(gè)IPhone的充電器類(Adaptee角色):
/**
* 充電器接口
*/
public interface ICharge {
void charge();
}
/**
* 蘋果手機(jī)充電器需要適配的角色(Adapee)
*/
public class AppleCharger implements ICharge{
public void charge(){
System.out.println("The ApplePhone is charging ...");
}
}
現(xiàn)在,要對(duì)這個(gè)特殊的充電器進(jìn)行適配,上個(gè)適配的接口(Target目標(biāo)角色):
/**
* 要對(duì)這個(gè)特殊的充電器進(jìn)行適配,適配器接口(Target角色)
*/
public interface IChargeAdapter {
void charge();
}
創(chuàng)建類的適配器:
/**
* 多接頭充電器,支持一邊充手機(jī),一邊充耳機(jī)(Adaper)
*/
public class MultipleJointsCharger extends AppleCharger implements IChargeAdapter{
@Override
public void charge() {
super.charge();
System.out.println("The Headset is charging ...");
}
}
啟動(dòng)類:
/**
* 啟動(dòng)類
*/
@SpringBootApplication
public class StartClass {
public static void main(String[] args){
MultipleJointsCharger multipleJointsCharger = new MultipleJointsCharger();
multipleJointsCharger.charge();
}
}
控制臺(tái):

2、對(duì)象適配器

故事情景:蘋果手機(jī)用蘋果充電器充電,安卓手機(jī)用安卓手機(jī)充電,現(xiàn)在需要一個(gè)萬能充電器能給這兩種手機(jī)充電。
創(chuàng)建兩個(gè)充電器類(Adaptee源角色):
/**
* 充電器接口
*/
public interface ICharge {
void charge();
}
/**
* 安卓手機(jī)充電器需要適配的角色(Adaptee)
*/
public class AndroidCharger implements ICharge{
@Override
public void charge() {
System.out.println("The AndroidPhone is charging ...");
}
}
/**
* 蘋果手機(jī)充電器需要適配的角色(Adaptee)
*/
public class AppleCharger implements ICharge{
public void charge(){
System.out.println("The ApplePhone is charging ...");
}
}
現(xiàn)在,要對(duì)這個(gè)特殊的充電器進(jìn)行適配,上個(gè)適配的接口(Target目標(biāo)角色):
/**
* 要對(duì)這個(gè)特殊的充電器進(jìn)行適配,適配器接口(Target角色)
*/
public interface IChargeAdapter {
void charge();
}
創(chuàng)建類的適配器:
/**
* 萬能充電器,類的適配器(Adaper)
*/
public class UniversalCharger implements IChargeAdapter{
private ICharge charge;
public UniversalCharger(ICharge charge){
this.charge = charge;
}
@Override
public void charge() {
charge.charge();
}
}
啟動(dòng)類:
/**
* 啟動(dòng)類
*/
@SpringBootApplication
public class StartClass {
public static void main(String[] args){
UniversalCharger universalCharger = new UniversalCharger(new AppleCharger())
universalCharger.charge();
UniversalCharger universalCharger1 = new UniversalCharger(new AndroidCharger());
universalCharger1.charge();
}
}
控制臺(tái):

總結(jié):
(1)類的適配器模式:當(dāng)希望將一個(gè)類轉(zhuǎn)換成滿足另一個(gè)新接口的類時(shí),可以使用類的適配器模式,創(chuàng)建一個(gè)新類,繼承原有的類,實(shí)現(xiàn)新的接口即可。
(2)對(duì)象的適配器模式:當(dāng)希望將一個(gè)對(duì)象轉(zhuǎn)換成滿足另一個(gè)新接口的對(duì)象時(shí),可以創(chuàng)建一個(gè)包裝類,持有原類的一個(gè)實(shí)例,在包裝類的方法中,調(diào)用實(shí)例的方法就行。