从AlertDialog看Builder模式

Builder模式

我们知道建造者模式,是将对象的创建过程与它的表示相分离开来,使得同样的创建过程有着不同的表示.它允许用户在不知道产品内部的构建细节,可以精细的控制产品的产品的构造流程.

Builder模式的组成

产品类的抽象类
Builder抽象类以及具体的Builder
Director指挥者

这么说比较抽象,我们来看一看AlertDialog的源码就知道Builder模式是怎么实现的!

AlertDialog源码

看源码首先看入口,比如构造函数,使用时调用的方法.

 protected AlertDialog(Context context, @StyleRes int themeResId) {
        this(context, themeResId, true);
    }

    AlertDialog(Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
        super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0,
                createContextThemeWrapper);

        mWindow.alwaysReadCloseOnTouchAttr();
        mAlert = new AlertController(getContext(), this, getWindow());
    }

相互调用,里面有个mAlert(AlertController),他是干嘛用的?留个疑问!



接着看调用的方法
    @Override
    public void setTitle(CharSequence title) {
        super.setTitle(title);
        mAlert.setTitle(title);
    }

 public void setButton(int whichButton, CharSequence text, Message msg) {
        mAlert.setButton(whichButton, text, null, msg);
    }
都是通过mAlert来操作的

再来看Builder:
  public static class Builder {
         // 一样有个AlertController p变量
         private final AlertController.AlertParams P;
         public Builder(Context context) {
                    this(context, resolveDialogTheme(context, 0));
                }
        public Builder(Context context, int themeResId) {
        // 创建了P
                    P = new AlertController.AlertParams(new ContextThemeWrapper(
                            context, resolveDialogTheme(context, themeResId)));
        }

    // 一些设置 将设置的东西存到了P里面
  public Builder setTitle(@StringRes int titleId) {
            P.mTitle = P.mContext.getText(titleId);
            return this;
        }
public Builder setIcon(@DrawableRes int iconId) {
            P.mIconId = iconId;
            return this;
        }

在看Create():

     public AlertDialog create() {
            ............
            // 创建了AlertDialog 
            final AlertDialog dialog = new AlertDialog(P.mContext, 0, false);
            P.apply(dialog.mAlert);
       .................

看apply
 public void apply(AlertController dialog) {

            // 之前将设置的参数放到了P,作为AlertController的成员变量
            // 然后将这些变量放到了AlertDialog的AlertController中
            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));
                }
         ...........................
            */
        }

经过以上的步骤,Builder的东西都放到了AlertDialog的AlertController中.

看关键的一步show

  public AlertDialog show() {
            final AlertDialog dialog = create();
            dialog.show();
            return dialog;
        }

 public void show() {

        // isSHow 省略
        mCanceled = false;

        if (!mCreated) {
            //走onCreate
            dispatchOnCreate(null);
        }
        // 走onStart()
        onStart();
        // 获取DecorView
        mDecor = mWindow.getDecorView();

        .........
        //将DecorView添加到mWindowManager中
        mWindowManager.addView(mDecor, l);

         // 发送显示Dialog的消息
        sendShowMessage();
    }

从上面我们可以看到Dialog也有自己的生命周期,视图的构建我们看看onCreate()

// 果然是通过AlertController 来控制
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAlert.installContent();
    }

 public void installContent() {
        final int contentView = selectContentView();
        mDialog.setContentView(contentView);
        setupView();
    }
 setupView();就是用来初始化AlertDialog的各个视图,这样AlertDialog就显示完毕了.

总结

从AlertDialog的Builder模式,我们并没有看到Director角色的出现,在经典的设计模式上做了一定的精简,灵活的运用了该模式.

应用

著名的图片加载库,Universal-Imge-Loader里面的初始化配置灵活的运用了该模式.

ImageLoaderConfig config = ImageLoaderConfig .Builder().set...set...(线程池数,默认图片,加载策略等)
ImageLoader.getInstance().init(config)
通过Builder模式,将ImageLoaderConfig的构造函数私有化,外部就不能访问内部属性,同时一些getter,setter就不会出现在用户的视野,用户仅仅能通过Builder来设置属性,内部通过apply(config)将builder设置的值赋给ImageLoaderConfig的各个属性.
这样就能将构建与表示相分离.

缺点

要说Builder模式的缺点的话就是产生了多余的Builder以及Director对象,消耗内存!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值