一、基本概念:
1、定义:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
2、适用场景:
- 多个组成部分,都可以装配到同一个对象,但是产生的结果不相同
- 相同的方法,不同的执行顺序,产生不同的事件结果
- 产品特别复杂,参数比较多的情况 例:电脑含有很多零配件,可以算是一个复杂对象。其中内存卡,主板、CPU等都是电脑的组成部分,如果构建一台电脑,不需要知道是如何组装的,只需要提供所需要的零配件型号,此时就可以用构建者模式。
3、优点:
- 封装性好,可以使使用者不必知道内部组成的细节
- 建造者独立,容易扩展
4、类图:
- Director:导演类,负责安排模块顺序,通知Builder开始构建
- Builder:抽象Builder类,规范产品的组建
- ConcreteBuilder:构造者实现类,实现抽象类的所有方法,并且返回一个组建好的对象
- Product:产品类
二、实例:
1、产品实体类:
public class Computer { private String cpu; private String mainBoard; private String ram; public String getCpu() { return cpu; } public void setCpu(String cpu) { this.cpu = cpu; } public String getMainBoard() { return mainBoard; } public void setMainBoard(String mainBoard) { this.mainBoard = mainBoard; } public String getRam() { return ram; } public void setRam(String ram) { this.ram = ram; }}复制代码
2、抽象Builder:
public abstract class Builder { public abstract void buildCpu(String cpu); public abstract void buildMainBoard(String mainBoard); public abstract void buildRam(String ram); public abstract Computer build();}复制代码
3、Builder实现类:
public class ComputerBuilder extends Builder { private Computer mComputer = new Computer(); @Override public void buildCpu(String cpu) { mComputer.setCpu(cpu); } @Override public void buildMainBoard(String mainBoard) { mComputer.setMainBoard(mainBoard); } @Override public void buildRam(String ram) { mComputer.setRam(ram); } @Override public Computer build() { return mComputer; }}复制代码
4、导演类:
起到封装的作用,避免深入到Builder内部的具体实现。可以传入不同的Builder实现对象。
public class ComputerDirector { private Builder mBuilder; private ComputerDirector(Builder builder) { this.mBuilder = builder; } public Computer createComputer(String cpu, String mainBoard, String ram) { mBuilder.buildCpu(cpu); mBuilder.buildMainBoard(mainBoard); mBuilder.buildRam(ram); return mBuilder.build(); }}复制代码
5、客户端调用:
public class ComputerTest { public static void main(String[] args){ Builder builder = new ComputerBuilder(); ComputerDirector director = new ComputerDirector(builder); director.createComputer("i3","my board", "4g"); }}复制代码
在实际使用过程中,有时会将Director进行省略,由调用者选择部分参数进行设置
三、AlertDialog
1、Builder
public static class Builder {
private final AlertController.AlertParams P; public Builder(Context context) { this(context, resolveDialogTheme(context, 0)); } public Builder(Context context, int themeResId) { P = new AlertController.AlertParams(new ContextThemeWrapper( context, resolveDialogTheme(context, themeResId))); } public Builder setTitle(@StringRes int titleId) { P.mTitle = P.mContext.getText(titleId); 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); //调用了AlertParams的apply方法 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; }}复制代码
Builder中定义了一些set方法用来设置Dialog的参数,Builder方法内部是给AlertController.AlertParams进行参数赋值
2、AlertDialog.AlertParams
public static class AlertParams { public final Context mContext; public final LayoutInflater mInflater; public int mIconId = 0; public Drawable mIcon; public int mIconAttrId = 0; public CharSequence mTitle; public View mCustomTitleView; public CharSequence mMessage; public CharSequence mPositiveButtonText; ...... public AlertParams(Context context) { mContext = context; mCancelable = true; mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } //将参数赋值给了Dialog public void apply(AlertController dialog) { if (mCustomTitleView != null) { dialog.setCustomTitle(mCustomTitleView); } else { if (mTitle != null) { dialog.setTitle(mTitle); } if (mIcon != null) { dialog.setIcon(mIcon); } if (mIconId != 0) { dialog.setIcon(mIconId); } if (mIconAttrId != 0) { dialog.setIcon(dialog.getIconAttributeResId(mIconAttrId)); } } if (mMessage != null) { dialog.setMessage(mMessage); } ...... }} 复制代码
3、基本使用
AlertDialog.Builder builder = new AlertDialog.Builder(this); // 设置参数builder.setTitle("") .setIcon(R.drawable.ic_launcher) .setMessage("");builder.create().show();复制代码
- 先创建一个Builder对象,通过Builder进行参数设置
- 内部会将这些参数传递给AlertDialog.AlertParams
- 在调用create方法时,AlertDialog.AlertParams再将参数设置给AlertDialog
- 最终通过show方法显示dialog
Builder模式通常作为配置类的构造器将配置的构造和表示分离,并且通过调用链实现,使代码调用更简洁。