一、概述
Builder模式直译过来就是构造者模式,它是用来构造复杂对象的一种创建型模式。用户不需要知道内部细节是如何构造的,这样可以更好的控制构造对象的流程。构造一个对象可能会很复杂,会有很多的构建参数,而builder模式就是将构造过程和构建参数分开,将构造过程隐藏,构建参数暴露出去,达到了解耦的目的。拿个组装电脑这个具体的例子说明,我们组装电脑的时候,我们知道需要组装cpu、内存条、主板、显卡等参数,而不用知道是怎么具体组装的,拿到店里店员给我们组装(自己装就不用杠了☻,或许这个例子并不是那么恰当)
二、使用
class CreateComputer{
//主板
var mBoard : String? = null
//cpu
var mCpu : String? = null
//内存
var mRam : String? = null
//显卡
var mGraphicsCard : String? = null
private constructor(board : String?,cpu : String?,ram : String?,graphicsCard : String?){
this.mBoard = board
this.mCpu = cpu
this.mRam = ram
this.mGraphicsCard = graphicsCard
}
class Builder{
private var board : String? = null
private var cpu : String? = null
private var ram : String? = null
private var graphicsCard : String? = null
fun setBoard(b:String?) : Builder{
board = b
return this
}
fun setCpu(c:String?) : Builder{
cpu = c
return this
}
fun setRam(r:String?) : Builder{
ram = r
return this
}
fun setGraphicsCard(g:String?) : Builder{
graphicsCard = g
return this
}
fun build() : CreateComputer{
return CreateComputer(board,cpu,ram,graphicsCard)
}
}
}
还是举上面组装电脑的栗子,创建一个CreateComputer类。可以看到,使用private私有化了构造方法,外界无法直接创建CreateComputer的对象;在CreateComputer有一个嵌套类,里面暴露出了构造相关参数的方法;最后再通过一个build()方法,调用了CreateComputer的构造方法,这样就创建了CreateComputer的对象并返回,我们就可以得到这个返回对象得到相关的构造参数。
class BuilderModeActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_builder_mode)
val myBuilder = CreateComputer.Builder()
val myComputer = myBuilder.setBoard("华硕B365m")
.setCpu("Intel i9-9900x")
.setRam("金士顿海盗船16G")
.setGraphicsCard("华硕GTX2080-super")
.build()
println("主板:${myComputer.mBoard} CPU:${myComputer.mCpu} 内存:${myComputer.mRam} 显卡:${myComputer.mGraphicsCard}")
}
}
在BuilderModeActivity类中对builder模式的使用,组装一台电脑。可以看到,先创建一个Builder对象,在这个对象中构造需要的组件参数,调用build()完成构造。这样就使用我们在使用builder模式的时候,无需知道内部细节是怎么构造的,主需要把相关组件参数传递进去就可以组装出一台电脑。
三、源码中的应用
在源码中builder模式的使用,我们能经常用到的就是AlertDialog,它的内部也是同样构造了一个Builder类,只是它把相关的构建参数封装在了AlertController.AlertParams对象中,最后通过create()方法构造出了一个AlertDialog对象。
...
public static class Builder {
private final AlertController.AlertParams P;
public Builder(Context context) {
this(context, resolveDialogTheme(context, ResourceId.ID_NULL));
}
public Builder(Context context, int themeResId) {
P = new AlertController.AlertParams(new ContextThemeWrapper(context, resolveDialogTheme(context, themeResId)));
}
public Context getContext() {
return P.mContext;
}
public Builder setTitle(@StringRes int titleId) {
P.mTitle = P.mContext.getText(titleId);
return this;
}
public Builder setTitle(CharSequence title) {
P.mTitle = title;
return this;
}
public Builder setCustomTitle(View customTitleView) {
P.mCustomTitleView = customTitleView;
return this;
}
public Builder setMessage(@StringRes int messageId) {
P.mMessage = P.mContext.getText(messageId);
return this;
}
...
public AlertDialog create() {
// Context has already been wrapped with the appropriate theme.
final AlertDialog dialog = new AlertDialog(P.mContext, 0, 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;
}
public AlertDialog show() {
final AlertDialog dialog = create();
dialog.show();
return dialog;
}
}
下面是AlertController的部分构造参数:
public class AlertController {
...
public static class AlertParams {
public int mIconId = 0;
public Drawable mIcon;
public CharSequence mTitle;
public View mCustomTitleView;
public CharSequence mMessage;
public CharSequence mPositiveButtonText;
public DialogInterface.OnClickListener mPositiveButtonListener;
...
}
...
}
四、总结
最后总结一下builder模式,使用private修饰构造方法,外界无法直接创建对象,只能通过内部Builder类的build方法;隐藏了构建对象的过程;暴露出给外部调用的方法,用于构造组件。