“Android設計模式”這個系列主要是對Android專案中的設計模式進行分析總結,學習自《Android 原始碼設計模式解析與實戰》,錯誤之處煩請指正~
Android設計模式系列文章:
一、 概述
1.1 定義
將一個複雜物件的構建與表示分離開來,使得同樣的構建過程可以建立不同的表示。
1.2 使用場景
-
相同的方法,不同的執行順序,產生不同的結果
-
多中屬性都可以裝配到一個物件中,但是產生的執行結果不同
-
複雜的產品類,或者產品類結果會隨呼叫順序發生改變
-
初始化一個物件特別複雜,如引數特別多,且很多引數都具有預設值時
1.3 分析
Builder模式將部件和組裝過程分離,使得構建過程和部件都可以自由擴充套件,從而降低兩者耦合度。
優點:
- 良好的封裝性,使用Builder模式可以使客戶端不必知道產品內部的組成細節
- Builder獨立,易於擴充套件
缺點:
- 會產生冗餘的Builder物件以及組裝物件,消耗記憶體
二、 實現
2.1 示例
Builder模式非常易於上手,我們通過分析一個簡單的demo來感受Builder模式的魅力。
EventBus
框架中的 EventBusBuilder
就採用 Builder 模式實現,我們來分析Builder模式的實現,EventBus 3.0 原始碼解析見 EventBus3.原始碼解析。
EventBusBuilder
是 EventBus
框架中的個性化配置類,從類名就可以看出這是一個 Builder 模式,通過Builder 物件來組裝個性化設定 EventBus
的各項引數配置,包括 是否通過Log輸出異常資訊logSubscriberExceptions 等。下面看看 EventBusBuilder
的相關原始碼。
public class EventBusBuilder {
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
boolean logSubscriberExceptions = true;//是否通過Log輸出異常資訊
boolean logNoSubscriberMessages = true;//是否通過Log輸出傳送事件無訂閱者資訊
boolean sendSubscriberExceptionEvent = true;//是否將內部異常資訊通過SubscriberExceptionEvent傳送出去
boolean sendNoSubscriberEvent = true;//是否將無訂閱者的時間通過NoSubscriberEvent傳送出去
boolean throwSubscriberException;//是否將內部異常資訊通過EventBusException丟擲
boolean eventInheritance = true;//傳送事件是否支援呼叫所有父類及實現的介面
boolean ignoreGeneratedIndex;//是否忽略生成被觀察者訂閱的方法(通過反射)
boolean strictMethodVerification;//是否開啟嚴格的方法驗證,(public,只有一個引數,不為static及abstract),非法則均丟擲異常
ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;//傳送事件的執行緒池
List<Class<?>> skipMethodVerificationForClasses;//對類忽略方法校驗,目前未實現
List<SubscriberInfoIndex> subscriberInfoIndexes;//通過annotation preprocessor生成的訂閱者方法list
EventBusBuilder() {
}
/**
* 設定 logSubscriberExceptions,預設為true
* @param logSubscriberExceptions
* @return
*/
public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {
this.logSubscriberExceptions = logSubscriberExceptions;
return this;
}
/**
* 設定 logNoSubscriberMessages,預設為 true
* @param logNoSubscriberMessages
* @return
*/
public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {
this.logNoSubscriberMessages = logNoSubscriberMessages;
return this;
}
/**
* 設定 sendSubscriberExceptionEvent,預設為 true
* @param sendSubscriberExceptionEvent
* @return
*/
public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {
this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;
return this;
}
/**
* 設定 sendNoSubscriberEvent,預設為 true
* @param sendNoSubscriberEvent
* @return
*/
public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {
this.sendNoSubscriberEvent = sendNoSubscriberEvent;
return this;
}
/**
* 設定 throwSubscriberException,預設為 false
* @param throwSubscriberException
* @return
*/
public EventBusBuilder throwSubscriberException(boolean throwSubscriberException) {
this.throwSubscriberException = throwSubscriberException;
return this;
}
/**
* 設定 eventInheritance,預設為 true
* @param eventInheritance
* @return
*/
public EventBusBuilder eventInheritance(boolean eventInheritance) {
this.eventInheritance = eventInheritance;
return this;
}
/**
* 設定 executorService
* @param executorService
* @return
*/
public EventBusBuilder executorService(ExecutorService executorService) {
this.executorService = executorService;
return this;
}
/**
* 設定 skipMethodVerificationForClasses
* @param clazz
* @return
*/
public EventBusBuilder skipMethodVerificationFor(Class<?> clazz) {
if (skipMethodVerificationForClasses == null) {
skipMethodVerificationForClasses = new ArrayList<>();
}
skipMethodVerificationForClasses.add(clazz);
return this;
}
/**
* 設定 ignoreGeneratedIndex
* @param ignoreGeneratedIndex
* @return
*/
public EventBusBuilder ignoreGeneratedIndex(boolean ignoreGeneratedIndex) {
this.ignoreGeneratedIndex = ignoreGeneratedIndex;
return this;
}
/**
* 設定 strictMethodVerification
* @param strictMethodVerification
* @return
*/
public EventBusBuilder strictMethodVerification(boolean strictMethodVerification) {
this.strictMethodVerification = strictMethodVerification;
return this;
}
/**
* 設定 subscriberInfoIndexes
* @param index
* @return
*/
public EventBusBuilder addIndex(SubscriberInfoIndex index) {
if(subscriberInfoIndexes == null) {
subscriberInfoIndexes = new ArrayList<>();
}
subscriberInfoIndexes.add(index);
return this;
}
/**
* 實現修改 EventBus 預設 EventBusBuilder(EventBus.defaultInstance)
* @return
*/
public EventBus installDefaultEventBus() {
synchronized (EventBus.class) {
if (EventBus.defaultInstance != null) {
throw new EventBusException("Default instance already exists." +
" It may be only set once before it's used the first time to ensure consistent behavior.");
}
EventBus.defaultInstance = build();
return EventBus.defaultInstance;
}
}
/**
* 通過 build 方式實現 EventBus 初始化
* @return
*/
public EventBus build() {
return new EventBus(this);
}
}
複製程式碼
上述程式碼中,EventBusBuilder
類可以設定 EventBus
中的 * logSubscriberExceptions、logNoSubscriberMessages、sendSubscriberExceptionEvent* 等引數,這些引數統一儲存在 EventBusBuilder
中。在呼叫 EventBusBuilder
類的 build()
函式時會建立 EventBus
,並且將各項配置用於到 EventBus
中去。
EventBusBuilder
採用 Builder 模式主要是初始化 EventBus
配置項引數複雜,並且很多引數具有預設值,在使用時可能只需要對部分引數進行修改,故採用 Builder 模式方便修改初始化。
2.2 小結
通過 2.1節 可以看出 Builder 模式使用非常方便,並且對於多引數屬性初始化來說,極大的簡化了工作。
在專案中合理的加入 Builder 模式吧~
三、小結
Builder 模式在 Android 開發中較為常用,通常作為配置類的構造器將配置的構建和表示分離開來,同時也實現了將配置類從目標類中抽離出來,避免了過多的 setter
方法。
Builder 模式比較常見的實現方式是通過呼叫鏈實現,這樣使得程式碼簡單易懂。
本文對 Builder模式 的分析到此就結束了,部分內容學習自 《Android原始碼設計模式 解析與實戰》。
附: