Android 經常使用設計模式(一)

來源:互聯網
上載者:User

標籤:抽象   動作   lin   file   普通話   就會   proxy   pattern   rgs   

由於項目變更的頻繁性,作為一名程式猿,我們須要掌握設計模式的必要性。就不言而喻~~。以下就是一些我自己學習的設計模式總結。
接下來,主要是針對幾個比較經常使用模式進行解說,主要是以下幾種:

  • 觀察者模式
  • 適配器模式
  • 代理模式
  • 原廠模式
  • 單例模式
  • 命令模式

1.觀察者模式(Observer Pattern)
釋義:觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同一時候監聽某一個主題對象,這個主題對象在狀態上發生變化時,會通知全部觀察者對象,使他們能夠自己主動更新自己。
故事理解:觀察者想知道公司全部MM的情況,僅僅要增加公司的MM情報郵件組即可了,tom負責搜集情報,當發現新情報時,不用一個一個通知我們,直接公布給郵件組。我們作為訂閱者(觀察者)就能夠及時收到情報啦。
常見執行個體:1.BaseAdapter.registerDataSetObserver和BaseAdapter.unregisterDataSetObserver雙方法來向BaseAdater注冊、登出一個DataSetObserver ; 2.使用ContentObserver去監聽資料庫變化。


適用情境:1.當對一個對象的改變須要同一時候改變其它對象,而不知道詳細有多少對象有待改變。2.當一個對象必須通知其它對象。而它又不能假定其它對象是誰.

觀察者模式主要有觀察者和被觀察者2個對象。在該模式中。Observable表示被觀察者,這個對象是一個抽象類別。僅僅能被繼承。 Observer表示觀察者,他是一個介面。所以觀察者能夠有多個。實現了該介面的類都是屬於觀察者。
這是網上一個生動仔細的demo:
被觀察者:

public class MyPerson extends Observable {    private int age;    private String name;    private String sax;    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;        setChanged();        notifyObservers();    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;        setChanged();        notifyObservers();    }    public String getSax() {        return sax;    }    public void setSax(String sax) {        this.sax = sax;    }    @Override    public String toString() {        return "MyPerson [age=" + age + ", name=" + name + ", sax=" + sax + "]";    }}

MyPerson是被觀察者,類中調用了setChange()以及notifyObservers()兩個方法。前者是告知資料改變,後者是發送訊號通知觀察者。

觀察者:

public class MyObserver implements Observer {    private int i;    private MyPerson myPerson;//觀察的對象    public MyObserver(int i){        System.out.println("我是觀察者---->" + i);        this.i = i;    }    public int getI() {        return i;    }    public void setI(int i) {        this.i = i;    }    public MyPerson getMyPerson() {        return myPerson;    }    public void setMyPerson(MyPerson myPerson) {        this.myPerson = myPerson;    }    @Override    public void update(Observable observable, Object data) {        System.out.println("觀察者---->"+ i +"得到更新!");        this.myPerson = (MyPerson)observable;        System.out.println(((MyPerson)observable).toString());    }}

觀察者須要實現Observer介面,當中僅僅有一個update方法。當觀察者收到 (被觀察者)的通知訊號。就會執行該動作。

詳細demo原始碼以及實現效果可點串連

2.適配器模式(Adapter Pattern)
釋義:把一個類的介面變換成client所期待的還有一種介面,從而使原本因介面原因不匹配而無法一起工作的兩個類能夠一起工作。

適配類能夠依據參數返還一個合適的執行個體給client。


故事理解:在朋友聚會上碰到了一個美女Sarah。從香港來的,可我不會說粵語。她不會說普通話,僅僅好求助於我的朋友kent了,他作為我和Sarah之間的Adapter,讓我和Sarah能夠相互交談了(也不知道他會不會耍我)。
常見執行個體:ListView用於顯示列表資料,可是作為列表資料集合有非常多形式。有Array,有Cursor,我們須要相應的適配器作為橋樑,處理相應的資料(並能形成ListView所須要的視圖)。
適用情境:1.業務的介面與工作的類不相容,(比方:類中缺少實現介面的某些方法)但又須要兩者一起工作。2. 在現有介面和類的基礎上為新的業務需求提供介面。

適配器模式分為類適配器模式和對象適配器模式。

關於類適配模式。由於java的單繼承,所以在已繼承一個類時。另外的僅僅能是介面,須要手動實現相應的方法,這樣在client就能夠建立任一種符合需求的子類。來實現詳細功能。而第二種對象適配器,它不是使用繼承再實現的方式,而是使用直接關聯,或者稱為託付的方式,詳細可見該部落格詳細介紹適配器模式(Adapter):類適配器、對象適配器

接下來就以ListView與ArrayAdapter來解說下
ListAdapter:

public interface ListAdapter {    public int getCount();    Object getItem(int position);    long getItemId(int position);    View getView(int position, View convertView, ViewGroup parent);    boolean isEmpty();}

ListView作為一個client,所須要的目標介面就是ListAdapter,包括getCount(),getItem(),getView()等幾個方法。為了相容List< T >資料類型的資料來源。專門定義了ArrayAdapter適配器,說白了。就是針對目標介面對資料來源進行相容修飾。

抽象類別BaseAdapter,省略了其它代碼,這裡僅僅列出兩個方法:

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {    // ... ...    public View getDropDownView(int position, View convertView, ViewGroup parent) {        return getView(position, convertView, parent);    }    public boolean isEmpty() {        return getCount() == 0;    }}

ArrayAdapter對List< T >進行封裝成ListAdapter的實現,滿足ListView的調用:

public class ArrayAdapter<T> extends BaseAdapter implements Filterable {    private List<T> mObjects;    //我僅僅列出這一個建構函式。大家懂這個意思即可    public ArrayAdapter(Context context, int textViewResourceId, T[] objects) {        init(context, textViewResourceId, 0, Arrays.asList(objects));    }    private void init(Context context, int resource, int textViewResourceId, List<T> objects) {        mContext = context;        mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);        mResource = mDropDownResource = resource;        mObjects = objects; //引用對象,也是表達了組合優於繼承的意思        mFieldId = textViewResourceId;    }    public int getCount() {        return mObjects.size();    }   public T getItem(int position) {        return mObjects.get(position);    }    public View getView(int position, View convertView, ViewGroup parent) {        return createViewFromResource(position, convertView, parent, mResource);    }    // ... ...}

我們就如此成功的把List< T > 作為資料來源以ListView想要的目標介面的樣子傳給了ListView。這事實上也是對象適配器的一種。

3.代理模式(Proxy Pattern)
釋義: 通過引入一個新的對象來實現對真實對象的操作或將新的對象作為真實對象的一個替身,這種實現機制是代理模式(為其它對象提供一種代理以控制對這個對象的訪問).
故事理解:校園代理是為他相應的上司作代理,而這個校園代理的工作就是訪問校園中的學生。比如對學生進行問卷之類的事。

學生就是官方說法中的其它對象,校園代理的上司就通過控制這個校園代理來控制對學生的訪問。
常見執行個體:ActivityManagerProxy類就是一個代理。它是ActivityManagerNative的代理,也就是說ActivityManagerProxy是所說的Proxy類。而ActivityManagerNative就相當於“上司角色“類,它們都有一個共同擁有的介面IActivityManager。ActivityManager。它相當於代理模式的client。在這個類中,能夠看到大量的getxxx函數,這些函數,都會調用到ActivityManagerNative類的getDefault()方法,而該方法會獲得一個共用的單例的IActivityManager引用。然後通過多態來調用代理中的實現
適用情境:代理模式的應用場合分幾種:遠程代理,虛擬代理,安全代理等,詳細可見為別人做嫁衣—-代理模式

請看以下一張結構圖(網上看到的一個仔細生動的範例):

Subject類:定義了RealSubject和Proxy的共用介面,這樣就能夠在不論什麼 使用RealSubject的地方都能夠用Proxy。
RealSubject類:定義Proxy所代表的真實實體。
Proxy類:儲存一個引用使得代理能夠訪問實體,並提供一個與Subject的介面同樣的介面。這樣代理就能夠用來替代實體。

接下來,我們來實現該模式:
1.Subject類 :Image.java

/** * Subject類 */public abstract class Image {    public abstract void displayImage();}

2.RealSubject類:RealImage.java

import com.andyidea.patterns.subject.Image;  /**   * RealSubject類   */  public class RealImage extends Image {      private String filename;      public RealImage(String filename) {           this.filename = filename;          loadImageFromDisk();      }      private void loadImageFromDisk() {          System.out.println("Loading   " + filename);      }      @Override      public void displayImage() {          System.out.println("Displaying " + filename);       }  } 

3.proxy類:ProxyImage.java

import com.andyidea.patterns.realsubject.RealImage;import com.andyidea.patterns.subject.Image;/** * Proxy類 */public class ProxyImage extends Image {    private String filename;    private Image image;    public ProxyImage(String filename) {         this.filename = filename;     }    @Override    public void displayImage() {        if(image == null){            image = new RealImage(filename);        }        image.displayImage();    }}

4.client測試類:ProxyClient.java

import com.andyidea.patterns.proxy.ProxyImage;import com.andyidea.patterns.subject.Image;/** * 代理模式client測試類 */public class ProxyClient {    public static void main(String[] args) {        System.out.println("Welcome to my Blog!" +"\n"                    +"Proxy Patterns." +"\n"                   +"-------------------------------");        Image mImage1 = new ProxyImage("My.Image1");        Image mImage2 = new ProxyImage("My.Image2");        mImage1.displayImage();        mImage2.displayImage();    }}

執行結果例如以下:

        Welcome to my Blog!          Proxy Patterns        -------------------------------         Loading   My.Image1         Displaying My.Image1         Loading   My.Image2          Displaying My.Image2

總結來說,代理類就是對實體儲存一個引用。同一時候也實現了實體一樣的介面方法,這樣。就能夠替代實體了!!

以上就是觀察者模式。適配器模式,代理模式的認識,接下來會在 Android 經常使用設計模式(二)裡,繼續對餘下的三種模式進行闡述。

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.