【設計模式筆記】(二)- Builder模式
1.簡述
Builder模式也就是建造者模式,先說定義,將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。
首先,將複雜物件的建立過程和部件的表示分離出來,其實就是把建立過程和自身的部件解耦,使得構建過程和部件都可以自由擴充套件,兩者之間的耦合降到最低。然後,再是相同的構建過程可以建立不同的表示,相同的組合也可以通過不同的部件建立出不同的物件。
可能使用場景
- 相同的方法,不同的執行順序,產生不同的結果時
- 多個部件(程式碼中就對應類的屬性),都可以裝配到一個物件中,但是產生的執行結果又不相同時
- 初始化一個物件特別複雜,引數多且很多引數都具有預設值時
這只是舉幾個比較合適的例子而已
2.實現
- Product —— 產品的抽象類
- Builder —— 抽象Builder類,規範產品的元件
- ConcreteBuilder —— 具體的Builder類,實現具體的組建過程
- Director —— 統一組裝過程
看到這裡可能回覺得這個模式怎麼和android平時使用的不太一樣啊!Builder一般不是隻有Product和Builder麼?
關於這點,有度娘過一下Builder模式,基本介紹都是這種結構,相對標準,這個標準的意思就是幫助學習該設計模式,並不是指一種用法,畢竟設計模式還是需要靈活使用。而沒有Director該環節的實現方式就是對Builder模式的一種簡化。
這是一個手機配置簡化的抽象類,設定CPU、OS以、記憶體大小以及運存大小
public abstract class Phone {
protected String mCPU;
protected String mOS;
protected int mMemorySize;
protected int mStorageSize;
public abstract void setCPU();
public abstract void setOS();
public void setMemorySize(int memorySize) {
this.mMemorySize = memorySize;
}
public void setStorageSize(int storageSize) {
this.mStorageSize = storageSize;
}
@Override
public String toString() {
return "{ \n CPU : " + mCPU + "\n OS : " + mOS +
" \n MemorySize : " + mMemorySize + "GB" +
" \n StorageSize : " + mStorageSize + "GB \n}";
}
}
具體的IPhoneX的類,由於CPU和系統是固定,而記憶體和運存運存可選。
public class IPhoneX extends Phone {
public IPhoneX(){}
@Override
public void setCPU() {
mCPU = "A11";
}
@Override
public void setOS() {
mOS = "iOS 11";
}
}
抽象的Builder類,作為主要隔離作用的類,Phone的API的每一個方法都有對應的build方法,並都返回自身來實現鏈式API。
public abstract class Builder {
//設定CPU
public abstract Builder buildCPU();
//設定系統
public abstract Builder buildOS();
//設定運存大小
public abstract Builder buildMemorySize(int memorySize);
//設定儲存大小
public abstract Builder buildStorageSize(int storageSize);
//建立一個Phone物件
public abstract Phone create();
}
IPhoneXBuilder
,具體的Builder
類
public class IPhoneXBuilder extends Builder {
private IPhoneX mIPhoneX = new IPhoneX();
@Override
public Builder buildCPU() {
mIPhoneX.setCPU();
return this;
}
@Override
public Builder buildOS() {
mIPhoneX.setOS();
return this;
}
@Override
public Builder buildMemorySize(int memorySize) {
mIPhoneX.setMemorySize(memorySize);
return this;
}
@Override
public Builder buildStorageSize(int storageSize) {
mIPhoneX.setStorageSize(storageSize);
return this;
}
@Override
public Phone create() {
return mIPhoneX;
}
}
Director類,負責構造Phone
public class Director {
Builder mBuilder = null;
public Director(Builder builder){
mBuilder = builder;
}
public void construct(int memorySize,int storageSize){
mBuilder.buildCPU()
.buildOS()
.buildMemorySize(memorySize)
.buildStorageSize(storageSize);
}
}
下面是測試程式碼
//構建器
Builder builder = new IPhoneXBuilder();
//Director
Director director = new Director(builder);
//封裝構建過程
director.construct(6,256);
//構建Phone,輸出相關資訊
Log.i(TAG, builder.create().toString());
通過具體的IPhoneXBuilder
類構建IPhoneX
物件,Director
封裝了構建Phone物件的過程,隱藏構建的細節。Builder
和Director
兩個部分起到了將物件的構建過程和物件的表示分離的作用。
之前也提到過,真是開發中Director
類一般會省略,直接使用Builder
,採用鏈式API進行組裝,在使用Buidler模式的過程中更加有效。
3.Android原始碼中得Builder模式實現
首先想到的就是AlertDialog.Builder
,AlertDialog.Builder
其實是AlertDialog
的靜態內部類,所有的dialog屬性都暫存在AlertController.AlertParams
的一個final物件中,以此來做到一個Builder物件只組裝一次,卻能構建出多個屬性相同的dialog。
這裡擷取了AlertDialog
中比較關鍵的程式碼,
public class AlertDialog extends AppCompatDialog implements DialogInterface {
final AlertController mAlert;
protected AlertDialog(@NonNull Context context, @StyleRes int themeResId) {
super(context, resolveDialogTheme(context, themeResId));
//構造AlertController物件
mAlert = new AlertController(getContext(), this, getWindow());
}
//此處省略不知道多少程式碼。。。
@Override
public void setTitle(CharSequence title) {
super.setTitle(title);
mAlert.setTitle(title);
}
//******* 內部類Builder *******
public static class Builder {
//儲存AlertDialog的相關屬性
private final AlertController.AlertParams P;
private final int mTheme;
public Builder(@NonNull Context context, @StyleRes int themeResId) {
P = new AlertController.AlertParams(new ContextThemeWrapper(
context, resolveDialogTheme(context, themeResId)));
mTheme = themeResId;
}
//...
public Builder setTitle(@StringRes int titleId) {
P.mTitle = P.mContext.getText(titleId);
return this;
}
//...
public AlertDialog create() {
// We can't use Dialog's 3-arg constructor with the createThemeContextWrapper param,
// so we always have to re-set the theme
final AlertDialog dialog = new AlertDialog(P.mContext, mTheme);
//將設定到Builder中得屬性設定到dialog的mAlert中,再由mAlert設定到view上
P.apply(dialog.mAlert);
dialog.setCancelable(P.mCancelable);
if (P.mCancelable) {
dialog.setCanceledOnTouchOutside(true);
}
dialog.setOnCancelListener(P.mOnCancelListener);
dialog.setOnDismissListener(P.mOnDismissListener);
if (P.mOnKeyListener != null) {
dialog.setOnKeyListener(P.mOnKeyListener);
}
return dialog;
}
public AlertDialog show() {
final AlertDialog dialog = create();
dialog.show();
return dialog;
}
}
}
還有一點值得關注,AlertDialog
中的AlertController
物件,是接收Builder
成員變數AlertController.AlertParams
中的各個引數。AlertController
與AlertController.AlertParams
不太相同的地方是,AlertController
中又真是的View和屬性設定,而AlertController.AlertParams
只是作為一個暫時存放屬性值得物件,在apply()
方法呼叫時將相關的屬性值傳遞給AlertDialog
的AlertController
物件,再由AlertController`物件設定到view上。
4.總結
Builder模式在Android開發中也是比較常用的,通常作為配置類的構建器,將配置的構建和表示分離,同時也是將配置從使用中隔離出來,避免過多的setter方法。在Builder模式的實現中經常通過鏈式呼叫實現,達到通俗易懂的目的。
優點:
- 良好的封裝性,使用者不用知道內部的實現細節
- 容易擴充套件,由於Builder的獨立存在擴充套件不會影響原有邏輯
缺點:
- 會產生多餘的
Builder
物件,可能還有Director
物件,佔用記憶體
像網路框架(或圖片載入框架)的Config的構建,也是Builder模式所適用的場景。總的來說,設計模式還是需要明白設計的主要目的,才能更好地使用各種模式去解決實際問題。
相關文章
- 設計模式:Builder模式概述設計模式UI
- Java設計模式之builder模式Java設計模式UI
- 設計模式-建造者模式(Builder)設計模式UI
- 設計模式--建造者模式(Builder Pattern)設計模式UI
- 設計模式-生成器模式Builder設計模式UI
- 【設計模式】- 生成器模式(Builder)設計模式UI
- 《設計模式》 - 3. 建立者模式( Builder )設計模式UI
- 設計模式(五)Builder構建者模式設計模式UI
- 設計模式十: 生成器模式(Builder Pattern)設計模式UI
- 重識設計模式-建造者模式(Builder Pattern)設計模式UI
- C#設計模式-建造者模式(Builder Pattern)C#設計模式UI
- 【設計模式】設計模式(一)-- 大話設計模式讀書筆記設計模式筆記
- Java設計模式學習筆記(二) 簡單工廠模式Java設計模式筆記
- 設計模式學習筆記(二)工廠模式、模板模式和策略模式的混合使用設計模式筆記
- 學習筆記-設計模式:MVC模式筆記設計模式MVC
- 設計模式筆記---工廠方法模式設計模式筆記
- 設計模式筆記(2)設計模式筆記
- JAVA設計模式筆記Java設計模式筆記
- 人人都會設計模式: 07、建造者模式--Builder設計模式UI
- Java設計模式學習筆記(一) 設計模式概述Java設計模式筆記
- 設計模式學習筆記——單例模式設計模式筆記單例
- Java 高效程式設計之 Builder 模式Java程式設計UI模式
- 設計模式實戰系列之@Builder和建造者模式設計模式UI
- 設計模式學習筆記設計模式筆記
- 學習筆記-設計模式筆記設計模式
- 設計模式之“物件效能模式”: Singleton 單例模式(筆記)設計模式物件單例筆記
- 設計模式學習筆記之工廠模式設計模式筆記
- php設計模式學習筆記PHP設計模式筆記
- JavaScript設計模式學習筆記JavaScript設計模式筆記
- Builder 模式UI模式
- 設計模式學習筆記之裝飾者模式設計模式筆記
- Java設計模式學習筆記(五) 單例模式Java設計模式筆記單例
- 設計模式(二)——單例模式設計模式單例
- 23種設計模式(二)---策略設計模式設計模式
- 一天一個設計模式(三) - 建造者模式(Builder)設計模式UI
- 設計模式之單例模式(《JavaScript設計模式與開發實踐》讀書筆記)設計模式單例JavaScript筆記
- Java設計模式學習筆記(四) 抽象工廠模式Java設計模式筆記抽象
- Java設計模式學習筆記(三) 工廠方法模式Java設計模式筆記