一文带你理解建造者模式

当一个对象内部具有很多个组成部分时,如果简单的通过构造器的方式去创建这个对象,则显得比较繁琐。一种情况是构造函数会接受很多个参数,一种是需要重载多个构造函数,或者是需要调用多次setter方法。在这时候,建造者模式就显得聪明很多。

定义

将一个复杂对象的构建与它的表示分离,使用同样的构建过程可以创建不同的表示。

场景

当初始化的一个对象特别复杂时,譬如,参数特别多而且都具有默认值。这是使用建造者模式比较多的场景。当然,还包括:

  1. 一个类的一系列方法在不同的调用顺序下,会产生不同的结果
  2. 一个类调用不同参数的构造器产生的实例,某些方法最终运行的结果不同

特点

  1. 隐藏构造细节
  2. 特有的建造者类Builder
  3. 简洁的调用(部分有序的链式调用)
  4. 更好的扩展性和良好的封装性

重要角色

产品类:需要构建的实例所属的类型,可以使接口,也可以是类

Builder:构建者模式核心类,辅助生成产品类实例的工具类

组装类:实施组装产品对象细节的管理类(大部分时候,这个角色由Builder担任)

源码分析

这里借助安卓系统对话框AlertDialog的构造过程进行说明。

	protected AlertDialog(@NonNull Context context) {
        this(context, 0);
    }

    /**
     * Construct an AlertDialog that uses an explicit theme.  The actual style
     * that an AlertDialog uses is a private implementation, however you can
     * here supply either the name of an attribute in the theme from which
     * to get the dialog's style (such as {@link R.attr#alertDialogTheme}.
     */
    protected AlertDialog(@NonNull Context context, @StyleRes int themeResId) {
        super(context, resolveDialogTheme(context, themeResId));
        mAlert = new AlertController(getContext(), this, getWindow());
    }

    protected AlertDialog(@NonNull Context context, boolean cancelable,
            @Nullable OnCancelListener cancelListener) {
        this(context, 0);
        setCancelable(cancelable);
        setOnCancelListener(cancelListener);
    }

在源码中可以看到AlertDialog的构造器是protected的,所以外部无法通过new关键字的形式创建AlertDialog对象。

在实际使用过程中,是通过内部类Builder来创建AlertDialog实例的。

	AlertDialog.Builder builder = new AlertDialog.Builder(this);
	AlertDialog alertDialog = builder.setIcon(R.drawable.iv).setCancelable(false).create();

稍微看一下Builder类的功能


    public static class Builder {
        private final AlertController.AlertParams P;
        private final int mTheme;

        public Builder(@NonNull Context context) {
            this(context, resolveDialogTheme(context, 0));
        }

        public Builder(@NonNull Context context, @StyleRes int themeResId) {
            P = new AlertController.AlertParams(new ContextThemeWrapper(
                    context, resolveDialogTheme(context, themeResId)));
            mTheme = themeResId;
        }

        @NonNull
        public AlertDialog create() {
            // We can't use Dialog's 3-arg constructor with the createThemeContextWrapper param,
            // so we always have to re-set the theme
            final AlertDialog dialog = new AlertDialog(P.mContext, mTheme);
            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的构造器也很简单。仅仅是实例化一个AlertController.AlertParams类型的成员变量,
用来存储创建AlertDialog的参数,在create方法中,对AlertDialog进行组装并返回组装对象。

AlertDialog类中,AlertDialog扮演了产品类的角色,内部类Builder扮演了建造者类和组装类的角色

总结

建造者模式的出发点是将复杂对象的构建过程和表示过程分离开来。通过中间建造者来实现对产品类的构建过程,这样可以避免使用大量的setter方法,而且在使用过程中,一般会采用调用链实现,使得代码更加简洁、易懂。

建造者模式的优点还在于它良好的封装性以及扩展性。通过建造者构建实例,不需要去了解实例对象内部的构造细节;建造者本身是独立的,因此具有更好的可扩展性。当然额外的Builder实例以及可能的组装者实例也是一种内存的浪费。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值