在Android開發過程當中,我發現不少安卓源代碼裏應用了設計模式,比較經常使用的有適配器模式(各類adapter),建造者模式(Alert Dialog的構建)等等。雖然咱們對大多數設計模式都有所瞭解,可是在應用設計模式的這個方面,感受不少人在這方面有所不足。因此,咱們能夠看看Android源代碼裏面是怎樣實現各類設計模式的,從而能夠加深咱們對設計模式的理解,從而方便咱們之後對它的應用。今天,咱們就來談談設計者模式(Builder Pattern)。設計模式
建造者模式(Builder Pattern)也叫作生成器模式,其定義以下:app
Separate the construction of a complex object from its representation so that the same construction process can create different representions. 將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。
它的意思就是將一個對象和怎麼構建這個對象分離開來,若是你想構建一個對象,你把這個消息告訴構建者,而且將本身對這個對象的各類要求告訴建造者,而後建造者根據這些要求進行搗鼓,而後,你所須要的一個對象就出來了。框架
咱們先來看下AlertDialog的源代碼(只列出關鍵代碼):ide
public class AlertDialog extends Dialog implements DialogInterface { ... protected AlertDialog(Context context, int theme) { this(context, theme, true); } AlertDialog(Context context, int theme, boolean createThemeContextWrapper) { super(context, resolveDialogTheme(context, theme), createThemeContextWrapper); mWindow.alwaysReadCloseOnTouchAttr(); mAlert = new AlertController(getContext(), this, getWindow()); } protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) { super(context, resolveDialogTheme(context, 0)); mWindow.alwaysReadCloseOnTouchAttr(); setCancelable(cancelable); setOnCancelListener(cancelListener); mAlert = new AlertController(context, this, getWindow()); } public static class Builder { private final AlertController.AlertParams P; private int mTheme; public Builder(Context context) { this(context, resolveDialogTheme(context, 0)); } public Builder(Context context, int theme) { P = new AlertController.AlertParams(new ContextThemeWrapper( context, resolveDialogTheme(context, theme))); mTheme = theme; } public Builder setMessage(CharSequence message) { P.mMessage = message; return this; } public AlertDialog create() { final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false); 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; } ... } }
從上面咱們能夠清楚地看到:AlertDialog的Build是一個靜態內部類(在有些狀況下,咱們會單獨定義一個Build抽象類,而後用具體類來繼承它,實現具體的功能)。咱們對AlertDialog設置的屬性會暫時保存在Build類的成員變量P(AlertController.AlertParams)中。同時,咱們注意到咱們設置的屬性,它都回返回自己的AlertBuild對象,這樣咱們就能夠不停地調用它設置的方法。post
若是咱們想得到這個AlertDialog。咱們就須要調用建造者的create()方法,在create()方法裏面它就會構造出一個Dialog實例,而且將咱們剛纔設置的屬性所有賦給AlertDialog,最後返回AlertDialog的實例。ui
看完了AlertDialog,咱們這邊再看一個實例,那就是Android開源框架UniversalImageLoader的DisplayImageOptions類,下面是它的一些核心代碼:this
public final class DisplayImageOptions { private final int imageResOnLoading; private final int imageResForEmptyUri; private final int imageResOnFail; private final Drawable imageOnLoading; private final Drawable imageForEmptyUri; private final Drawable imageOnFail; private final boolean resetViewBeforeLoading; private final boolean cacheInMemory; private final boolean cacheOnDisk; private final ImageScaleType imageScaleType; private final Options decodingOptions; private final int delayBeforeLoading; private final boolean considerExifParams; private final Object extraForDownloader; private final BitmapProcessor preProcessor; private final BitmapProcessor postProcessor; private final BitmapDisplayer displayer; private final Handler handler; private final boolean isSyncLoading; private DisplayImageOptions(Builder builder) { imageResOnLoading = builder.imageResOnLoading; imageResForEmptyUri = builder.imageResForEmptyUri; imageResOnFail = builder.imageResOnFail; imageOnLoading = builder.imageOnLoading; imageForEmptyUri = builder.imageForEmptyUri; imageOnFail = builder.imageOnFail; resetViewBeforeLoading = builder.resetViewBeforeLoading; cacheInMemory = builder.cacheInMemory; cacheOnDisk = builder.cacheOnDisk; imageScaleType = builder.imageScaleType; decodingOptions = builder.decodingOptions; delayBeforeLoading = builder.delayBeforeLoading; considerExifParams = builder.considerExifParams; extraForDownloader = builder.extraForDownloader; preProcessor = builder.preProcessor; postProcessor = builder.postProcessor; displayer = builder.displayer; handler = builder.handler; isSyncLoading = builder.isSyncLoading; } ... public static class Builder { private int imageResOnLoading = 0; private int imageResForEmptyUri = 0; private int imageResOnFail = 0; private Drawable imageOnLoading = null; private Drawable imageForEmptyUri = null; private Drawable imageOnFail = null; private boolean resetViewBeforeLoading = false; private boolean cacheInMemory = false; private boolean cacheOnDisk = false; private ImageScaleType imageScaleType = ImageScaleType.IN_SAMPLE_POWER_OF_2; private Options decodingOptions = new Options(); private int delayBeforeLoading = 0; private boolean considerExifParams = false; private Object extraForDownloader = null; private BitmapProcessor preProcessor = null; private BitmapProcessor postProcessor = null; private BitmapDisplayer displayer = DefaultConfigurationFactory.createBitmapDisplayer(); private Handler handler = null; private boolean isSyncLoading = false; public Builder() { decodingOptions.inPurgeable = true; decodingOptions.inInputShareable = true; } /** * Stub image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware * image aware view} during image loading * * @param imageRes Stub image resource * @deprecated Use {@link #showImageOnLoading(int)} instead */ @Deprecated public Builder showStubImage(int imageRes) { imageResOnLoading = imageRes; return this; } /** * Incoming image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware * image aware view} during image loading * * @param imageRes Image resource */ public Builder showImageOnLoading(int imageRes) { imageResOnLoading = imageRes; return this; } /** Builds configured {@link DisplayImageOptions} object */ public DisplayImageOptions build() { return new DisplayImageOptions(this); } ... } }
它比AlertDialog實現更爲簡單一點,直接將屬性定義在Builder的成員變量中,而後將Builder對象返回給DisplayImageOptions中直接進行賦值,這樣作的話,將初始化對象的複雜邏輯所有交給了Builder類,而使咱們須要的DisplayImageOptions顯得很是的乾淨,功能也至關的簡潔明瞭。設計
最後,若是本文有什麼疏漏的話,還請指正。rest
口號:Make things Interesting!code