Builder
Builder模式是一步步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细的控制对象的构造流程。该模式是为了将构造复杂对象的过程和它的部件解耦,使得构建过程和部件的表示隔离开来。
栗子
我们通过一个例子来引出Builder模式。假设有一个Person类,我们通过该Person类来构建一大批人,这个Person类里有很多 属性,最常见的比如name,age,weight,height等等,并且我们允许这些值不被设置,也就是允许为null,该类的定义如下:
|
|
于是你就可以这样创建各个需要的对象:
可以想象一下这样创建的坏处,最直观的就是四个参数的构造方法的最后面的两个参数到底是什么意思,可读性不怎么好,还有一个问题就是当有很多参数时,编写这个构造函数就会显得异常麻烦,这时候便可以用Builder模式。
我们给Person增加一个静态内部类Builder类,并修改Person类的构造函数,代码如下:
在Builder类里定义了一份与Person类一模一样的变量,通过一系列的成员函数进行设置属性值,但是返回值都是this,也就是都是Builder对象,最后提供了一个build函数用于创建Person对象,返回的是Person对象,对应的构造函数在Person类中进行定义,也就是构造函数的入参是Builder对象,然后依次对自己的成员变量进行赋值,对应的值都是Builder对象中的值。此外Builder类中的成员函数返回Builder对象自身的另一个作用就是让它支持链式调用,使代码可读性大大增强。
于是我们就可以这样创建Person类:
总结
定义一个静态内部类Builder,内部的成员变量和外部类一样
Builder类通过一系列的方法用于成员变量的赋值,并返回当前对象本身(this)
Builder类提供一个build方法或者create方法用于创建对应的外部类,该方法内部调用了外部类的一个私有构造函数,该构造函数的参数就是内部类Builder
外部类提供一个私有构造函数供内部类调用,在该构造函数中完成成员变量的赋值,取值为Builder对象中对应的值
Android源码中Builder模式实现
在Android源码中,最常用到的Builder模式就是AlertDialog.Builder,使用该Builder来构造复杂的AlertDialog对象。
我们先来看一下AlertDialog的相关源码:
接下来看一下AlertDialog的内部类Builder的源码:
Builder类可以设置AlertDialog中的title、message、button等参数,这些参数存储在类型为AlertController.AlertParams的成员变量P中,AlertController.AlertParams中包含了AlertDialog视图中对应的成员变量。在调用Builder的creat函数时会创建AlertDialog,并且将Builder成员变量中P的参数应用到AlertDialog的mAlert对象中,即P.apply(dialog.mAlert)代码段,看看AlertParams类中apply方法的实现:
在apply方法中,只是将AlertParams参数设置到AlertController中,我们来看一下AlertController类:
AlertController.AlertParams 持有AlertController的所有属性,在调用builder里的设置属性方法时,就是给AlertController.AlertParams做一个缓存。在调用了builder 的show方法之后。里面在调用具体dialog的show方法显示弹窗。
那么AlertDialog在建造者模式中担任的是指挥者,Bilder就是具体的建造者。采用了链式调用。AlertController是产品,而AlertController.AlertParams是产品的缓存。比如我调用了两次setTitle(),在缓存时后一次会覆盖前一次,这样就解决了开发者冲动调用的问题。最后不论是调用Builder的show方法,还是调用调用AlertDialog的show方法。都是允许的。
我们来看一下Dialog的show方法:
在调用底层的show方法时,会先进行一次判断,第一次show之后mShowing已经设为true。那么第二次调用时,判断到已经显示,就不会再次调用绘制逻辑
在show方法中主要做了如下几件事:
- 通过dispatchOnCreate函数来调用AlertDialog的onCreate函数
- 然后调用AlertDialog的onStart函数
- 最后将Dialog的DecorView的添加到WindowManager中
那么建造者模式就到这儿了,更详细的挖掘还得去挖源码