Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中的設計模式-適配器模式

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

編輯:關於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 Adaptee
I 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 Adaptee
I 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> 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。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved