Android設計模式之Builder模式

Builder設計模式


定義:

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

參與者:

  • Product:被構建的複雜對象,ConcreteBuilder用來創建該對象的內部表示,並定義它的裝配過程。
  • Builder:抽象接口,用來定義創建Product對象的各個組成部件操作
  • ConcreteBuilder:Builder接口的具體實現。可以定義多個,是實際構建Product對象的地方,同時會提供一個返回Product的接口
  • Director:Builder接口的構造者和使用者

Builder模式的變種

目的:

減少對象創建過程中引入多個重載構造函數,可選參數以及setters函數過度使用導致的不必要的複雜性。

例子講解:

public class User {
    private final String mFirstName;//必選
    private final String mLastName;//必選
    private final String mGender;//可選屬性
    private final int mAge;//可選屬性
    private final String mPhoneNo;//可選屬性

    private User(UserBuilder userBuilder) {
        mFirstName = userBuilder.firstName;
        mLastName = userBuilder.lastName;
        mGender = userBuilder.gender;
        mAge = userBuilder.age;
        mPhoneNo = userBuilder.phoneNo;
    }

    public String getmFirstName() {
        return mFirstName;
    }

    public String getmLastName() {
        return mLastName;
    }

    public String getmGender() {
        return mGender;
    }

    public int getmAge() {
        return mAge;
    }

    public String getmPhoneNo() {
        return mPhoneNo;
    }

    public static class UserBuilder{
        private final String firstName;
        private final String lastName;
        private String gender;
        private int age;
        private String phoneNo;
        public UserBuilder(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }
        public UserBuilder gender(String gender) {
            this.gender = gender;
            return this;
        }
        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }
        public UserBuilder phoneNo(String phoneNo) {
            this.phoneNo = phoneNo;
            return this;
        }
        public User build() {
            return new User(this);
        }
    }
}

//使用
//這樣子就構建了一個User對象,當然,後面的屬性也可以選填或者不填。
       User user = new User.UserBuilder("黃","小明").age(15).gender("qqq").phoneNo("456789").build();

優點

  • 減少對象創建過程中引入多個重載構造函數,可選參數以及setters函數過度使用導致的不必要的複雜性。
  • 代碼容易維護,容易使用。後續想要添加屬性,直接添加一個相對應的屬性和其方法即可。
  • 如果採取無參構造函數,接着使用set來設置屬性,那麼User類的實例狀態不連續。直到第五個set函數被調用時,該類的實例才具有完整連續的狀態,也就意味着類調用者會看到該類實例的不連續狀態。
  • 設定final修飾屬性值不可變。

缺點

  • 需要編寫很多的樣板代碼,需要在內部類UserBuilder中重複外部類User的屬性定義。

變種Builder模式的自動化生成

在AndroidStudio中,安裝名爲InnerBuilder的插件。
InnerBuilder

編寫User類代碼的時候,只需要把屬性名確定下來,然後單擊鼠標右鍵,打開Generate菜單,選擇Builder按鈕,在配置對話框中進行相關配置的勾選即可。

舉個例子


public class Person {
    private final String mLastName;//必填
    private final String mFirstName;//必填
    private int mHeight;//選填
    private int mBodyWeight;//選填
}

CreateBuilder

第一個打勾的意思是:生成final字段的構造器方法。
如果不打勾,那麼生成的代碼就和我們上面的User類代碼一致。

生成後的代碼:


public class Person {
    private final String mLastName;//必填
    private final String mFirstName;//必填
    private int mHeight;//選填
    private int mBodyWeight;//選填

    private Person(Builder builder) {
        mLastName = builder.mLastName;
        mFirstName = builder.mFirstName;
        mHeight = builder.mHeight;
        mBodyWeight = builder.mBodyWeight;
    }

    public static final class Builder {
        private String mLastName;
        private String mFirstName;
        private int mHeight;
        private int mBodyWeight;

        public Builder() {
        }

        public Builder mLastName(String val) {
            mLastName = val;
            return this;
        }

        public Builder mFirstName(String val) {
            mFirstName = val;
            return this;
        }

        public Builder mHeight(int val) {
            mHeight = val;
            return this;
        }

        public Builder mBodyWeight(int val) {
            mBodyWeight = val;
            return this;
        }

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

利用工具來進行類的Builder模式構建真的很快,效率是槓槓的。

變種Builder模式的應用

1. Android系統對話框AlertDialog的使用

AlertDialog alertDialog = new AlertDialog.Builder(this)
                .setTitle("對話框標題")
                .setMessage("對話框內容")
                .setIcon(R.drawable.ic_launcher_background)
                .create();
        alertDialog.show();

2. 網絡請求框架OkHttp的請求封裝

這個大家可以閱讀下OkHttp3的源碼,裏面大量應用了Builder設計模式。
Request:
在這裏插入圖片描述
在這裏插入圖片描述

OkHttpClient:
666

所以,這都體現出Builder設計模式的好處:
將一個複雜對象與它的表示分離,使得同樣的構建過程可以創建不同的表示。
減少對象創建過程中引入多個重載構造函數,可選參數以及setters函數過度使用導致的不必要的複雜性。


參考:《Android高級進階》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章