Java適配器模式

概述

適配器模式把一個類的接口變換成客戶端所期待的另一種接口辆苔,從而使原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作挤巡。

適配器模式的用途

用電器做例子,筆記本電腦的插頭一般都是三相的,即除了陽極绵患、陰極外,還有一個地極悟耘。而有些地方的電源插座卻只有兩極落蝙,沒有地極。電源插座與筆記本電腦的電源插頭不匹配使得筆記本電腦無法使用。這時(shí)候一個三相到兩相的轉(zhuǎn)換器(適配器)就能解決此問題筏勒,而這正像是本模式所做的事情移迫。

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

適配器模式有類的適配器模式對象的適配器模式兩種不同的形式。

類適配器模式

類的適配器模式把適配的類的API轉(zhuǎn)換成為目標(biāo)類的API管行。


在上圖中可以看出厨埋,Adaptee類并沒有sampleOperation2()方法,而客戶端則期待這個方法病瞳。為使客戶端能夠使用Adaptee類揽咕,提供一個中間環(huán)節(jié),即類Adapter套菜,把Adaptee的API與Target類的API銜接起來亲善。Adapter與Adaptee是繼承關(guān)系,這決定了這個適配器模式是類的

模式所涉及的角色有:

1.目標(biāo)(Target)角色:這就是所期待得到的接口逗柴。注意:由于這里討論的是類適配器模式蛹头,因此目標(biāo)不可以是類。

2.源(Adapee)角色:現(xiàn)在需要適配的接口戏溺。

3.適配器(Adaper)角色:適配器類是本模式的核心渣蜗。適配器把源接口轉(zhuǎn)換成目標(biāo)接口。顯然旷祸,這一角色不可以是接口耕拷,而必須是具體類。

源代碼

/**
 * 目標(biāo)接口托享,或稱為標(biāo)準(zhǔn)接口
 */
public interface Target {

    public void request();

}
/**
 * 標(biāo)準(zhǔn)實(shí)現(xiàn)
 */
public class ConcreteTarget implements Target {


    @Override
    public void request() {
        System.out.println("標(biāo)準(zhǔn)實(shí)現(xiàn)");
    }
}
/**
 * 已存在的骚烧、具有特殊功能、但不符合我們既有的標(biāo)準(zhǔn)接口的類
 */
public class Adaptee {

    public void specificRequest() {
        System.out.println("不標(biāo)準(zhǔn)實(shí)現(xiàn)闰围,特殊實(shí)現(xiàn)");
    }

}
/**
 * 適配器
 */
public class Adapter extends Adaptee implements Target {

    /**
     * 適配器繼承了被適配對象赃绊,同時(shí)實(shí)現(xiàn)了標(biāo)準(zhǔn)接口,可以重寫的方法中調(diào)用父類(Adaptee)的方法羡榴,完成適配
     */
    @Override
    public void request() {
        super.specificRequest();
    }
}
/**
 * 客戶端
 */
public class Client {

    public static void main(String[] args) {

        //標(biāo)準(zhǔn)接口實(shí)現(xiàn)
        Target target1 = new ConcreteTarget();
        target1.request();

        //通過適配器實(shí)現(xiàn)標(biāo)準(zhǔn)接口
        Target target2 = new Adapter();
        target2.request();
    }

}

上面這種實(shí)現(xiàn)的適配器稱為類適配器碧查,因?yàn)?Adapter 類既繼承了 Adaptee (被適配類),也實(shí)現(xiàn)了 Target 接口(因?yàn)?Java不支持多繼承校仑,所以這樣來實(shí)現(xiàn))忠售,在 Client 類中我們可以根據(jù)需要選擇并創(chuàng)建任一種符合需求的子類,來實(shí)現(xiàn)具體功能

對象適配器模式

與類的適配器模式一樣迄沫,對象的適配器模式把被適配的類的API轉(zhuǎn)換成為目標(biāo)類的API稻扬,與類的適配器模式不同的是,對象的適配器模式不是使用繼承關(guān)系連接到Adaptee類邢滑,而是使用委派關(guān)系連接到Adaptee類腐螟。



  從上圖可以看出,Adaptee類并沒有sampleOperation2()方法困后,而客戶端則期待這個方法乐纸。為使客戶端能夠使用Adaptee類,需要提供一個包裝(Wrapper)類Adapter摇予。這個包裝類包裝了一個Adaptee的實(shí)例汽绢,從而此包裝類能夠把Adaptee的API與Target類的API銜接起來。Adapter與Adaptee是委派關(guān)系侧戴,這決定了適配器模式是對象的宁昭。

源代碼

/**
 * 適配器
 */
public class Adapter implements Target {

    // 直接關(guān)聯(lián)被適配類
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    /**
     * 使用委托的方式完成特殊功能
     */
    @Override
    public void request() {
        adaptee.specificRequest();
    }
}
public class Client {

    public static void main(String[] args) {

        //通過構(gòu)造方法傳入適配對象
        Adapter adapter = new Adapter(new Adaptee());
        adapter.request();

    }

}

適配器模式的優(yōu)點(diǎn)

1.更好的復(fù)用性

系統(tǒng)需要使用現(xiàn)有的類,而此類的接口不符合系統(tǒng)的需要酗宋。那么通過適配器模式就可以讓這些功能得到更好的復(fù)用积仗。

2.更好的擴(kuò)展性

在實(shí)現(xiàn)適配器功能的時(shí)候,可以調(diào)用自己開發(fā)的功能蜕猫,從而自然地?cái)U(kuò)展系統(tǒng)的功能寂曹。

適配器模式的缺點(diǎn)

過多的使用適配器,會讓系統(tǒng)非常零亂回右,不易整體進(jìn)行把握隆圆。比如,明明看到調(diào)用的是A接口翔烁,其實(shí)內(nèi)部被適配成了B接口的實(shí)現(xiàn)渺氧,一個系統(tǒng)如果太多出現(xiàn)這種情況,無異于一場災(zāi)難蹬屹。因此如果不是很有必要侣背,可以不使用適配器,而是直接對系統(tǒng)進(jìn)行重構(gòu)哩治。

缺省適配模式

缺省適配(Default Adapter)模式為一個接口提供缺省實(shí)現(xiàn)秃踩,這樣子類型可以從這個缺省實(shí)現(xiàn)進(jìn)行擴(kuò)展,而不必從原有接口進(jìn)行擴(kuò)展业筏。作為適配器模式的一個特例憔杨,缺省是適配模式在JAVA語言中有著特殊的應(yīng)用。

在很多情況下蒜胖,必須讓一個具體類實(shí)現(xiàn)某一個接口消别,但是這個類又用不到接口所規(guī)定的所有的方法。通常的處理方法是台谢,這個具體類要實(shí)現(xiàn)所有的方法寻狂,那些有用的方法要有實(shí)現(xiàn),那些沒有用的方法也要有空的朋沮、平庸的實(shí)現(xiàn)蛇券。

這些空的方法是一種浪費(fèi),有時(shí)也是一種混亂。除非看過這些空方法的代碼纠亚,程序員可能會以為這些方法不是空的塘慕。即便他知道其中有一些方法是空的,也不一定知道哪些方法是空的蒂胞,哪些方法不是空的图呢,除非看過這些方法的源代碼或是文檔。

缺省適配模式可以很好的處理這一情況骗随「蛑可以設(shè)計(jì)一個抽象的適配器類實(shí)現(xiàn)接口,此抽象類要給接口所要求的每一種方法都提供一個空的方法鸿染。此抽象類可以使它的具體子類免于被迫實(shí)現(xiàn)空的方法指蚜。

缺省適配模式的結(jié)構(gòu)

缺省適配模式是一種“平庸”化的適配器模式。


源代碼

public interface AbstractService {
    public void serviceOperation1();
    public int serviceOperation2();
    public String serviceOperation3();
}
public abstract class ServiceAdapter implements AbstractService{

    @Override
    public void serviceOperation1() {
    }

    @Override
    public int serviceOperation2() {
        return 0;
    }

    @Override
    public String serviceOperation3() {
        return null;
    }

}

可以看到涨椒,接口AbstractService要求定義三個方法姚炕,分別是serviceOperation1()、serviceOperation2()丢烘、serviceOperation3()柱宦;而抽象適配器類ServiceAdapter則為這三種方法都提供了平庸的實(shí)現(xiàn)。因此播瞳,任何繼承自抽象類ServiceAdapter的具體類都可以選擇它所需要的方法實(shí)現(xiàn)掸刊,而不必理會其他的不需要的方法。

適配器模式的用意是要改變源的接口赢乓,以便于目標(biāo)接口相容忧侧。缺省適配的用意稍有不同,它是為了方便建立一個不平庸的適配器類而提供的一種平庸實(shí)現(xiàn)牌芋。

在任何時(shí)候蚓炬,如果不準(zhǔn)備實(shí)現(xiàn)一個接口的所有方法時(shí),就可以使用“缺省適配模式”制造一個抽象類躺屁,給出所有方法的平庸的具體實(shí)現(xiàn)肯夏。這樣,從這個抽象類再繼承下去的子類就不必實(shí)現(xiàn)所有的方法了犀暑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末驯击,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子耐亏,更是在濱河造成了極大的恐慌徊都,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件广辰,死亡現(xiàn)場離奇詭異暇矫,居然都是意外死亡主之,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門李根,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杀餐,“玉大人,你說我怎么就攤上這事朱巨。” “怎么了枉长?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵冀续,是天一觀的道長。 經(jīng)常有香客問我必峰,道長洪唐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任吼蚁,我火速辦了婚禮凭需,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘肝匆。我一直安慰自己粒蜈,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布旗国。 她就那樣靜靜地躺著枯怖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪能曾。 梳的紋絲不亂的頭發(fā)上度硝,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機(jī)與錄音寿冕,去河邊找鬼蕊程。 笑死,一個胖子當(dāng)著我的面吹牛驼唱,可吹牛的內(nèi)容都是我干的藻茂。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼玫恳,長吁一口氣:“原來是場噩夢啊……” “哼捌治!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起纽窟,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤肖油,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后臂港,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體森枪,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡视搏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了县袱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浑娜。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖式散,靈堂內(nèi)的尸體忽然破棺而出筋遭,到底是詐尸還是另有隱情,我是刑警寧澤暴拄,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布漓滔,位于F島的核電站,受9級特大地震影響乖篷,放射性物質(zhì)發(fā)生泄漏响驴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一撕蔼、第九天 我趴在偏房一處隱蔽的房頂上張望豁鲤。 院中可真熱鬧,春花似錦鲸沮、人聲如沸琳骡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽日熬。三九已至,卻和暖如春肾胯,著一層夾襖步出監(jiān)牢的瞬間竖席,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工敬肚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留毕荐,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓艳馒,卻偏偏與公主長得像憎亚,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子弄慰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

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