Android設計模式之Builder模式
阿新 • • 發佈:2018-12-16
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的外掛。
編寫User類程式碼的時候,只需要把屬性名確定下來,然後單擊滑鼠右鍵,開啟Generate選單,選擇Builder按鈕,在配置對話方塊中進行相關配置的勾選即可。
舉個例子
public class Person {
private final String mLastName;//必填
private final String mFirstName;//必填
private int mHeight;//選填
private int mBodyWeight;//選填
}
第一個打勾的意思是:生成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:
所以,這都體現出Builder設計模式的好處:
將一個複雜物件與它的表示分離,使得同樣的構建過程可以建立不同的表示。
減少物件建立過程中引入多個過載建構函式,可選引數以及setters函式過度使用導致的不必要的複雜性。
參考:《Android高階進階》