天天看點

new AlertDialog.Builder(this).setxx引發的胡思亂想

    • 一前言
    • 二建造者模式
    • 三為何dialog使用builder模式
    • 四一般用Builder建立對象的一般方法
    • 五AlertDialog中的Builder方法
      • Builder構造函數
      • AlertDialogBuilder的public AlertDialog create法
    • 六參考資料

一、前言

今天寫着alertDialog0,突然想到直接new一個alertDialog對象 為何此種寫法。直覺上的感覺是這是用builder模式來建立對象。

二、建造者模式

印象中的建造者模式一直是以前項目中那樣,對象的建造過程有固定的模式,而這種模式和他的實作無關。有一個builder借口,定義這個建造過程方法。具體的builder實作類來實作。

我們一般搞一個導演類,傳入一個builder對象作為導演類的構造參數,調用導演類的construt(或者叫build)函數建構對象。

之前我們項目是自動生成項目背景代碼,我們是自動生成java類對象(包名,導入包,屬性,方法)

大話設計模式中舉例是說 建構一個人,先建構頭,手之類的

三、為何dialog使用builder模式

很明顯這裡不是為了上面的這種常見的builder模式的場景,網上查了一下,alertDialog的成員變量諸多。構造對象有兩種選擇

1. 寫多個構造函數,每個構造函數包含多個不同的參數這種寫法可能會導緻我們有時需要傳入null作為參數(參數最多的一種包含所有成員變量,這種通用性非常強)。但是這樣看起來非常臃腫,而且傳入null總讓人感覺怪怪的

2. 我們隻寫包含最通用的參數最少的構造方法,其他的通過get/set來給參數指派

但是這種可能會導緻我們的對象沒有完全建立(語義上的沒有完全建立,比如說我們需要構造名為小明,12歲,男,六年級)的對象,但是我們構造函數提供了姓名年齡,我們set了性别,但是沒有set年級,這時洩漏出去的對象,其實不是我們所需要的對象。這時嚴重不合理的。

這時我們可以使用builder比如builder中提供同樣的構造函數(姓名、年齡)後面set完性别和年齡之後調用create才會建立

這樣能很大程度上避免上面所述的缺點

Builder bulder = new StudentBuilder(name,age).setSex(male).setGrade();
Student student = bulder.create();
           

四、一般用Builder建立對象的一般方法

  1. 一般builder作為目标類的内部類,目标類構造函數設為protected強制使用builder來構造對象。
  2. 一般進一步取消目标類中的set方法,那麼該類的對象将會成為不可變對象(不考慮反射的情況)。

    不太明白到底有沒有必要将其做成那種不可變對象。

    如何建立不可變對象和最常見的不可變對象String則涉及到另一個話題參考資料2、3、4

    不可變對象的應用場景有待思考、思考、思考說三遍

五、AlertDialog中的Builder方法

Builder構造函數

P = new AlertController.AlertParams(new ContextThemeWrapper(
                    context, resolveDialogTheme(context, theme)));
           

構造了一個AlertController對象P,從源碼中可以看出,之後的setTitle之類的資訊都是set到了這個對象中。

AlertDialog.Builder的public AlertDialog create法

final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
            P.apply(dialog.mAlert);
            ....
           
  1. 首先看第一句new AlertDialog
.....
  mWindow.alwaysReadCloseOnTouchAttr();
  mAlert = new AlertController(getContext(), this, getWindow());
           

就是說Builder.craete的時候建立了一個AlertController對象malert

3. 再看第二句P.apply(dialog.mAlert);

這句是将之前set進P對象的資訊全部賦給AlertDialog中AlertController類的對象mAlert,然後傳回建立的對象。(該對象隻是個空架子,真正核心的東西在AlertController裡面)該類是android内部類,可以用source Insight追蹤

其實在看源碼的時候一直奇怪為什麼搞個AlertController,聯想到之前看到的Facebook的圖檔加載控件Fresco
new AlertDialog.Builder(this).setxx引發的胡思亂想

感覺應該不是巧合,這麼做應該是處于某些方面的考慮。目前層次太低,說不出個是以然

回頭還要去請大神指教

六、參考資料

  1. 使用Builder模式建立對象
  2. 如何用建造者模式建立不可變類
  3. 如何寫一個不可變類
  4. Java中的String對象是不可變的嗎