適配器模式(新手推薦)

好久沒更新了,今天給大家更新一篇設(shè)計(jì)模式文章——適配器模式。如果你做過Android開發(fā),那么你肯定對(duì)適配這個(gè)詞很熟悉。適配的作用就是讓我們的應(yīng)用程序能適用于各大主流的Android手機(jī)平臺(tái)。

適配,通俗地講,就是將極具個(gè)性的人,加以合適的引導(dǎo),讓其發(fā)揮其最大的作用。這個(gè)極具個(gè)性的人,就是Adaptee(適配者),發(fā)揮作用就是Target(我們的目標(biāo)),引導(dǎo)的這個(gè)人就是Adapter(適配器)。

舉個(gè)簡(jiǎn)單的例子,想必這個(gè)段子大家之前都聽過。段子這么說,12306的老板說,我們開發(fā)個(gè)網(wǎng)上售票的系統(tǒng)。老板下達(dá)命令給經(jīng)理,經(jīng)理把這個(gè)項(xiàng)目外包給高校的老師來做,高校的老師說,同學(xué)們給你們個(gè)畢設(shè)題目,限什么時(shí)候完成。(當(dāng)然這僅僅是個(gè)段子,實(shí)際肯定不是這樣的,12306真的已經(jīng)很不錯(cuò)了,為了引起大家學(xué)習(xí)的興趣,就當(dāng)嘩眾取寵吧)。

我們簡(jiǎn)化下中間的層層關(guān)系,留下3個(gè)主要的角色,一個(gè)是老板,一個(gè)是經(jīng)理,一個(gè)是學(xué)生。老板提出需求Target,老板不懂技術(shù),所以實(shí)際干活的是學(xué)生Adaptee。

你可能會(huì)問了,為什么需要經(jīng)理呢?

為什么不是老板直接和學(xué)生交流呢?當(dāng)然不行,倒不是因?yàn)槊孀拥膯栴},而是老板還有更重要的事情做,做整體的調(diào)度以及重大策略的決斷,這個(gè)項(xiàng)目只是其中的一個(gè)決定而已,所以是不方便也沒時(shí)間與學(xué)生直接溝通的,所以經(jīng)理Adapter出現(xiàn)了,負(fù)責(zé)向上級(jí)匯報(bào),以及與學(xué)生溝通。

那么用關(guān)系圖如何描述呢?

類適配器結(jié)構(gòu)圖

由圖可以看出,在Manager里面,我們實(shí)際調(diào)用的是Student的codingBuild()方法。那么如何用偽代碼實(shí)現(xiàn)呢?

class Manager implements Boss extends Student{

    @Override
    public void buildWebSystem(){

        codingBuild();
    }

}

上面就是類適配器的簡(jiǎn)單寫法,那么這么寫有沒有什么問題呢?

  1. 我們默認(rèn)Target是Interface,萬一Target類是個(gè)抽象類呢?我們知道Java是不支持多繼承的,所以這么寫肯定是有問題的。

  2. 如果Adaptee是final類型,那么就不能被繼承。

  3. 我們知道盡量少用繼承,多用組合。

那么有沒有其他寫法呢?所以對(duì)象適配器出現(xiàn)了。

class Manager implements Boss{

    private Student stu;//適配者

    public void setStudent(Student stu){

        this.stu = stu;
    }

    @Override
    public void buildWebSystem(){
    
        tu.codingBuild();
    }
    
}

我們可以看到,在適配器(Adapter)類中持有一個(gè)適配者(Adaptee)對(duì)象,在適配器的方法中調(diào)用該適配者的方法。

那么這樣寫有什么好處呢?

  1. 我們不用關(guān)心具體系統(tǒng)是如何實(shí)現(xiàn)的,所以對(duì)Adapter是透明的,將任務(wù)委托給Adaptee來實(shí)現(xiàn),只要知道達(dá)到我們的任務(wù)要求就可以了,也不用改動(dòng)現(xiàn)有的組織結(jié)構(gòu)。

  2. 假如我們對(duì)該適配者所做的工作不滿意,我們可以隨時(shí)更換其他的適配者,而不用改動(dòng)太多代碼。

那么適配者模式的使用場(chǎng)景呢?

  1. 不想了解具體的業(yè)務(wù)實(shí)現(xiàn)或者無法了解到具體的業(yè)務(wù)實(shí)現(xiàn)時(shí)可以使用該模式。因?yàn)閷?duì)調(diào)用者是透明的,我只需要制定規(guī)范,將具體實(shí)現(xiàn)“外包”給Adaptee來做;
  2. 如果需求更換較為頻繁,需要將具體的實(shí)現(xiàn)靈活性提高的時(shí)候可以使用該模式。說得專業(yè)點(diǎn)就是更換算法更為方便;
  3. 如果想使得具體實(shí)現(xiàn)(Adaptee)的復(fù)用性更好,可以使用該模式。

適配者模式基本上說完了,是不是很簡(jiǎn)單?

稍微拓展一下,說一下雙向適配器。雙向適配器(Adapter)同時(shí)持有Target和Adaptee。簡(jiǎn)單的示例代碼說下。

class Manager implements Boss extends Student{

    private Boss boss; // Target

    private Student stu; //Adaptee

    public setBoss(Boss boss){
        this.boss = boss;
    }
    
    public setStudent(Student stu){
        this.stu = stu;
    }

    @Override
    public void buildWebSystem(){
    
        tu.codingBuild();
    }
    
    public void codingBuild(){

        boss.buildWebSystem();
    }
    
}

這種實(shí)現(xiàn)我見得不多,作為了解。

還有一種缺省適配器有必要說一下。假設(shè)我們現(xiàn)在有接口類A里面有很多方法。

interface A{

    public void methodA();
    public void methodB();
    public void methodC();
    ...
}

我們現(xiàn)在有個(gè)類B要用到A接口里面的方法methodA(),怎么辦呢?很簡(jiǎn)單啊,直接讓B實(shí)現(xiàn)接口A不行嗎?當(dāng)然行。但是我們就必須為了這個(gè)methodB()而實(shí)現(xiàn)methodA()、methodC()...如果A里面的方法數(shù)目很多,那么將在我們的B類中出現(xiàn)大量的無用代碼,因?yàn)槌薽ethodA()都是空實(shí)現(xiàn)。有沒有比較好的實(shí)現(xiàn)方式呢?

//適配者接口
public interface A {

    public void methodA();
    public void methodB();
    public void methodC();
    public void methodD();
}

//缺省適配器類
public abstract class B implements A {

    @Override
    public void methodA() {
        
    }

    @Override
    public void methodB() {
        
    }

    @Override
    public void methodC() {
        
    }

    @Override
    public void methodD() {
        
    }
}

//具體業(yè)務(wù)類
public class C extends B {

    @Override
    public void methodA() {
        //TODO
    }
}

由代碼可以看出,我們?cè)谥虚g引入了一個(gè)抽象類B,用于對(duì)接口A中的所有方法空實(shí)現(xiàn)。最后在C中具體實(shí)現(xiàn)我們想要的目標(biāo)方法。

這么做的好處呢?

雖然也出現(xiàn)了沒用的代碼,但是我們這么做只需要讓這些代碼出現(xiàn)一次,而不是沒一個(gè)新的類中都要空實(shí)現(xiàn)一遍。

那么為什么B要是abstract的呢?

我是這么理解的,因?yàn)锽中所有的方法都是空實(shí)現(xiàn),所以這個(gè)類沒實(shí)際意義,真正起作用的是具體的實(shí)現(xiàn)類C,這里面具體實(shí)現(xiàn)我們想要的功能。為了避免大家實(shí)例化這個(gè)沒實(shí)際用處的類,所以聲明為abstract類型。每個(gè)類都有自己的職責(zé)以及名字,A(適配者接口),B(缺省適配器類),C(具體業(yè)務(wù)類)。

好了,適配器模式基本上說完了,希望可以給新手一點(diǎn)點(diǎn)幫助。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容