Android中的設計模式-適配器模式

來源:互聯網
上載者:User

標籤:設計模式   適配器模式   android   

適配器模式

從名字上就可以看出適配器是為了針對介面不匹配的情況,而做出的相容方法,
假設我們有一個已經存在的類Adaptee,其中有一些已經存在並實現好的方法methodA。但是客戶不希望調用這個類,而是希望調用一個特定的介面例如Target介面。
於是如果想要調用Adaptee.methodA()方法,建立一個Adapter類實現客戶要求的Target介面,Target介面中假設客戶希望調用callMethodA()方法來實現Adaptee.methodA()方法功能。能夠想到的就是以下兩種方式:

類的適配器模式

讓Adapter類實現Target介面介面同時繼承Adaptee類,這樣Adapter類就繼承了Adaptee.methodA(),在其callMethodA()中調用父類的methodA()方法即可。客戶建立Adapter類對象,就可以通過Target介面調用Adapter.methodA()。

類圖

代碼實現等待被適配的Adaptee
public class Adaptee {    public void methodA(){        System.out.println("I am the methodA in Adaptee");    }}
客戶期待的Target介面
public interface Target {    public void callMethodA();    public void otherMethod();}
繼承了Adaptee並實現Target介面的適配者
public class Adapter extends Adaptee implements Target {    @Override    public void callMethodA() {        super.methodA();    }    @Override    public void otherMethod() {        System.out.println("I am the otherMethod in Adapter");    }}
客戶類測試
public class Client {    public static void main(String[] args) {        Adapter mAdapter = new Adapter();        mAdapter.callMethodA();        mAdapter.otherMethod();    }}
輸出結果
I am the methodA in AdapteeI am the otherMethod in Adapter
對象的適配器模式

讓Adapter類中持有一個Adaptee類的執行個體,在Adapter類實現Target介面的methodA()方法時,在其中調用Adaptee執行個體的methodA()方法即可。

類圖

代碼實現

在上面的類的適配器基礎上,只需要修改Adapter和客戶類即可。

繼承了Adaptee並實現Target介面的適配者
public class Adapter implements Target {    private Adaptee mAdaptee;    public Adapter(Adaptee mAdaptee) {        this.mAdaptee = mAdaptee;    }    @Override    public void callMethodA() {        this.mAdaptee.methodA();    }    @Override    public void otherMethod() {        System.out.println("I am the otherMethod in Adapter");    }}
客戶類測試
public class Client {    public static void main(String[] args) {        Adaptee mAdaptee=new Adaptee();        Adapter mAdapter = new Adapter(mAdaptee);        mAdapter.callMethodA();        mAdapter.otherMethod();    }}

輸出結果也是一樣的

輸出結果
I am the methodA in AdapteeI am the otherMethod in Adapter
兩種適配器的對比

兩種模式各有利弊,類的適配器模式已經繼承了Adaptee類,就沒法再繼承其他的類,這時它的弊端,不過好處就是邏輯比較清晰,適合只適配單一的Adaptee的情況。對象的適配器模式則沒有繼承的限制,採用彙總的方式來適配待適配的類。個人個傾向於對象的適配器模式這種適配器方式,耦合性更低。

預設適配器模式

適配器還有第三種模式,看起來和上面的兩種適配器模式不太一樣,
對於一個定義了較多方法的介面,我們實現該介面的時候,一來實現這麼多的方法很麻煩。二來有些方法我們並不需要,都實現了反而混淆了重點。
為瞭解決這個問題,就是用一個抽象類別繼承該介面,並在抽象類別中使用空實現來實現介面中的方法。(也不一定,有些情況抽象類別中會有介面中的方法的預設實現,而繼承它的子類中只需要完成其特有的一些方法,或者在原有方法的基礎上進行增加。例如Android中的PhoneBase類,BaseAdapter類等)。

類圖代碼實現
public interface Target {    public void A();    public void B();    public void C();    public void D();    public void E();    public void F();}public abstract class AbstractTarget implements Target {    @Override    public void A() {    }    //可以留一個B方法不實現,B還是抽象的,留給子類必須實現    @Override    public void C() {        System.out.println("I am C in AbstractTarget");    }    @Override    public void D() {    }    @Override    public void E() {    }    @Override    public void F() {    }}public class ConcreteTarget extends AbstractTarget {    @Override    public void B() {//B是必須實現的        System.out.println("I am B in ConcreteTarget");    }    @Override    public void A() {//選擇性的重寫A和C方法        System.out.println("I am A in ConcreteTarget");    }    @Override    public void C() {        super.C();        System.out.println("I am C in ConcreteTarget");    }}
測試
    public static void main(String[] args) {        Target mTarget = new ConcreteTarget();        mTarget.A();        mTarget.B();        mTarget.C();    }
Android中的適配器模式

Android中最常見的適配器模式就屬於Android中的Adapter了,其應用融合了預設適配器模式和對象的適配器模式
抽象類別BaseAdapter實現ListAdapter和SpinnerAdapter兩個介面,而這兩個介面都是繼承自Adapter介面,這兩個介面分別又定義了自己的方法

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter 

不過BaseAdapter中並未實現介面中的全部方法
SimpleAdapter則繼承了BaseAdapter,並實現了所有沒實現的介面方法,有些BaseAdapter已經實現的方法,並沒有實現。

public class SimpleAdapter extends BaseAdapter

這裡就是上面的預設適配器模式。

那麼對象的適配器呢,
當我們使用SimpleAdapter時,例如:

ListView.setAdapter(new SimpleAdapter(this, getData(path),                android.R.layout.simple_list_item_1, new String[] { "title" },                new int[] { android.R.id.text1 }));

先看一下SimpleAdapter建構函式

    public SimpleAdapter(Context context, List<? extends Map<String, ?>> data,            int resource, String[] from, int[] to)

其中第2個參數是一個Map的隊列,對應每一個List的Item的資料,第3個參數則是展開這個Item的View的layout資源的整形ID。第4個參數from數組是第2個參數的Map的key,最後一個參數to數組則是from參數的每一個key對應的資料放置在哪個組件裡。

在ListView調用onMeasure確定組件尺寸時,就會調用到mAdapter.getCount(),調用這個SimpleAdapter的getCount()函數:

    public int getCount() {        return mData.size();    }    public Object getItem(int position) {        return mData.get(position);    }

間接調用之前建立SimpleAdapter時建構函式傳遞的data資料。
在繪製的時候,則會調用

mAdapter.getView(position, null, this)

擷取適配器所適配的資料所對應的View來進行繪製。

所以這裡SimpleAdapter就是對data對象的對象適配器模式,如果不使用適配器,ListView直接持有data資料當然也可以得到資料。但是ListView使用Adapter的精髓就是不需要去管資料是什麼,只需要建立不同的Adapter,就可以做出不同效果,含有不同組件的ListView。

Android中的設計模式-適配器模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.