Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發中無處不在的設計模式——Builder模式

Android開發中無處不在的設計模式——Builder模式

編輯:關於Android編程

 

那麼什麼是Builder模式呢。你通過搜索,會發現大部分網上的定義都是

將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示

但是看完這個定義,並沒有什麼卵用,你依然不知道什麼是Builder設計模式。在此個人的態度是學習設計模式這種東西,不要過度在意其定義,定義往往是比較抽象的,學習它最好的例子就是通過樣例代碼。

我們通過一個例子來引出Builder模式。假設有一個Person類,我們通過該Person類來構建一大批人,這個Person類裡有很多屬性,最常見的比如name,age,weight,height等等,並且我們允許這些值不被設置,也就是允許為null,該類的定義如下。

public class Person {
    private String name;
    private int age;
    private double height;
    private double weight;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }
}

然後我們為了方便可能會定義一個構造方法。

    public Person(String name, int age, double height, double weight) {
        this.name = name;
        this.age = age;
        this.height = height;
        this.weight = weight;
    }

或許為了方便new對象,你還會定義一個空的構造方法

    public Person() {
    }

甚至有時候你很懶,只想傳部分參數,你還會定義如下類似的構造方法。

  public Person(String name) {
        this.name = name;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

於是你就可以這樣創建各個需要的對象

Person p1=new Person();
Person p2=new Person(張三);
Person p3=new Person(李四,18);
Person p4=new Person(王五,21,180);
Person p5=new Person(趙六,17,170,65.4);

可以想象一下這樣創建的壞處,最直觀的就是四個參數的構造函數的最後面的兩個參數到底是什麼意思,可讀性不怎麼好,如果不點擊看源碼,鬼知道哪個是weight哪個是height。還有一個問題就是當有很多參數時,編寫這個構造函數就會顯得異常麻煩,這時候如果換一個角度,試試Builder模式,你會發現代碼的可讀性一下子就上去了。

我們給Person增加一個靜態內部類Builder類,並修改Person類的構造函數,代碼如下。

public class Person {
    private String name;
    private int age;
    private double height;
    private double weight;

    privatePerson(Builder builder) {
        this.name=builder.name;
        this.age=builder.age;
        this.height=builder.height;
        this.weight=builder.weight;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    static class Builder{
        private String name;
        private int age;
        private double height;
        private double weight;
        public Builder name(String name){
            this.name=name;
            return this;
        }
        public Builder age(int age){
            this.age=age;
            return this;
        }
        public Builder height(double height){
            this.height=height;
            return this;
        }

        public Builder weight(double weight){
            this.weight=weight;
            return this;
        }

        public Person build(){
            return new Person(this);
        }
    }
}

從上面的代碼中我們可以看到,我們在Builder類裡定義了一份與Person類一模一樣的變量,通過一系列的成員函數進行設置屬性值,但是返回值都是this,也就是都是Builder對象,最後提供了一個build函數用於創建Person對象,返回的是Person對象,對應的構造函數在Person類中進行定義,也就是構造函數的入參是Builder對象,然後依次對自己的成員變量進行賦值,對應的值都是Builder對象中的值。此外Builder類中的成員函數返回Builder對象自身的另一個作用就是讓它支持鏈式調用,使代碼可讀性大大增強。

於是我們就可以這樣創建Person類。

Person.Builder builder=new Person.Builder();
Person person=builder
        .name(張三)
        .age(18)
        .height(178.5)
        .weight(67.4)
        .build();

有沒有覺得創建過程一下子就變得那麼清晰了。對應的值是什麼屬性一目了然,可讀性大大增強。

其實在Android中, Builder模式也是被大量的運用。比如常見的對話框的創建

AlertDialog.Builder builder=new AlertDialog.Builder(this);
AlertDialog dialog=builder.setTitle(標題)
        .setIcon(android.R.drawable.ic_dialog_alert)
        .setView(R.layout.myview)
        .setPositiveButton(R.string.positive, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        })
        .setNegativeButton(R.string.negative, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        })
        .create();
dialog.show();

其實在java中有兩個常見的類也是Builder模式,那就是StringBuilder和StringBuffer,只不過其實現過程簡化了一點罷了。

我們再找找Builder模式在各個框架中的應用。

如Gson中的GsonBuilder,代碼太長了,就不貼了,有興趣自己去看源碼,這裡只貼出其Builder的使用方法。

GsonBuilder builder=new GsonBuilder();
Gson gson=builder.setPrettyPrinting()
        .disableHtmlEscaping()
        .generateNonExecutableJson()
        .serializeNulls()
        .create();

還有EventBus中也有一個Builder,只不過這個Builder外部訪問不到而已,因為它的構造函數不是public的,但是你可以在EventBus這個類中看到他的應用。

public static EventBusBuilder builder() {
    return new EventBusBuilder();
}
public EventBus() {
    this(DEFAULT_BUILDER);
}
EventBus(EventBusBuilder builder) {
    subscriptionsByEventType = new HashMap, CopyOnWriteArrayList>();
    typesBySubscriber = new HashMap

再看看著名的網絡請求框架OkHttp

Request.Builder builder=new Request.Builder();
Request request=builder.addHeader(,)
    .url()
    .post(body)
    .build();

除了Request外,Response也是通過Builder模式創建的。貼一下Response的構造函數

  private Response(Builder builder) {
    this.request = builder.request;
    this.protocol = builder.protocol;
    this.code = builder.code;
    this.message = builder.message;
    this.handshake = builder.handshake;
    this.headers = builder.headers.build();
    this.body = builder.body;
    this.networkResponse = builder.networkResponse;
    this.cacheResponse = builder.cacheResponse;
    this.priorResponse = builder.priorResponse;
  }

可見各大框架中大量的運用了Builder模式。最後總結一下

定義一個靜態內部類Builder,內部的成員變量和外部類一樣 Builder類通過一系列的方法用於成員變量的賦值,並返回當前對象本身(this) Builder類提供一個build方法或者create方法用於創建對應的外部類,該方法內部調用了外部類的一個私有構造函數,該構造函數的參數就是內部類Builder 外部類提供一個私有構造函數供內部類調用,在該構造函數中完成成員變量的賦值,取值為Builder對象中對應的值

 

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