通过理论,代码示例,Android源码来学习建造者模式
介绍
Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细的控制对象的构造流程,该模式是为了将构建复杂对象的过程和它的部件解耦,使得构建过程和创建过程隔离开来。
定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
使用场景
- 相同的方法,不同的执行顺序,产生不同的事件结果时。
- 当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时。
简单代码示例
这里比如我们第一次初始化应用的时候,需要初始化一些事物,比如默认记住密码,自动登录,开机登录,崩溃重启等等。
1 | package com.devyk.android_dp_code.builder; |
使用:
1 | //直接链式调用 |
Output:
1 | loginManager:LoginManager{isSavePwd=false, isAutoLogin=true, isBootLauncher=true, isCrashOnRestart=true} |
上述代码中,通过具体的 Builder 类来具体构建 LoginManager 需要的属性,最后通过链式调用,结构变得更加清晰,更加容易控制。
Android 源码中 AlertDialog 的 Builder 模式全面解析
在 Android 源码中,最常用之一的 Builder 模式 AlertDialog.Builder, 通过 Builder 来构建复杂的 AlertDialog 对象。请先看它的使用方式:
1 | private void showAlertDialog(Context context) { |
从 AlertDialog.Builder(context) 可以看出 AlertDialog 是一个 Builder 建造者模式,通过 Builder 对象,组装 Dialog 的各个部分,将 Dialog 的构造和表示进行分离。下面请看 AlertDialog Builder 的相关源码;
1 | import com.android.internal.R; |
上述代码中,Builder 类可以设置 AlertDialog 中的 title , message , buttom 等参数,这些参数都存储在 Builder 成员变量 p 中,p 中包含了与 AlertDialog 视图中对应的成员变量。在调用 Builder 类的 create 函数时,此时才真正的创建 AlertDialog,并且将 Builder p 保存的参数交于 AlertDialog mAlert 对象中,既 p.apply(mAlert);我们可以看下 apply 源码:
1 | public void apply(AlertController dialog) { |
在 apply 函数中,只是将 AlertParams 参数设置到 AlertControler 中,当我们调用 show 就能显示对话框了,我们具体来看下 show 的源码实现:
1 | /** |
在 show() 中主要做了如下几个事儿:
- 通过dispatchOnCreate 函数调用 AlertDialog 生命周期 onCreate 函数;
- 然后在调用 onStart
- 最后通过 windowManager 把 Dialog 的 DecorView 添加进去
那么按照构建,内容视图应该是在生命周期的 onCreate 里面
1 |
|
虽然 installContent 代码少,但是及其重要,它调用了 Window 对象的 setContentView, 此处的 setContentView 与 Activity setContentView 中的实现一模一样,都是调用 window 的方法。
最后 setupView 就是初始化 AlertDialog 布局中各个参数,在调用完该函数之后 Dialog 的视图内容就全部显示完毕了,而这些各区域的视图都属于 mAlertDialogLayout 布局中的子 View ,Window 对象关联了mAlertDialogLayout 的整个布局树,当调用完 setupView 之后整个视图树的数据也就填充完毕,当用户调用 show 函数时, WindowManager 会将 window 对象的 DecorView (也就是 mAlertDialogLayout 对应的视图)添加到用户的窗口上,并且显示出来。到这里 Dialog 就出现在了手机屏幕中。
实战
经过简单示例与分析源码中的 Builder 模式,相信大家对建造者模式已经有了一定了解了,现在我们就 Builder 模式来对ImageLoader 示例 改造。请看改造后的 ImageLoader
1 | //增加了 Builder 配置类 |
通过上面代码可以看到 ImageLoader 需要的业务,都可以在 ImageLoaderConfig Builder 配置。
1 | /** |
使用:
1 | /** |
通过配置之后就可以正常使用了,各种 setter 函数不会再用户调用 ImageLoader 方法时出现在视野中,它已经被隔离到了 Builder 模式中。清晰、简单的 API 也是一个开源库必须要保证的地方。
总结
Builder 模式在 Android 源码,开源库(Okhttp…)等常用,将配置的构建和表示分离开来,同时也是将配置从目标类中隔离出来,避免过多的 setter,Builder 模式比较常见的实现形式就是链式调用,这样使得代码更加简洁,易懂。
优点:
- 良好的封装性,使用建造者模式可以是客服端不必知道产品内部组成细节。
- 独立,易扩展。
缺点:
- 会产生多余的 Builder 对象,消耗内存。