安卓设计模式(三)Builder模式

作者: uncochen | 来源:发表于2016-09-30 11:05 被阅读942次

Builder模式也叫建造者模式,属于创建性模式,一般用于复杂对象的创建
该模式可以将构建复杂对象的过程和它的部件解耦,使得构建过程和部件的表示隔离开来

该系列其他文章:

Android中的使用场景

  • 复杂对象的创建,内部包含多个部件或者零件,都可以装配到一个对象中.如AlertDialog.Builder()

      new AlertDialog.Builder(this)
              .setPositiveButton("确定", null)
              .setTitle("请求权限")
              .setCancelable(false)
              .setMessage(messageResId)
              .show();
    
  • 用于框架的初始化,初始化之后无法对框架内部数据再做改动.如FileDownloader框架的初始化:

      FileDownloadConfiguration.Builder builder = new FileDownloadConfiguration.Builder(this);
      builder.configFileDownloadDir(StorageUtils.getFilesDirectory(mContext).getAbsolutePath() + File.separator + "pdf");
      builder.configRetryDownloadTimes(2);
      FileDownloadConfiguration configuration = builder.build();
      FileDownloader.init(configuration);
    
  • 创建或初始化对象时,参数多,并且参数都具有默认值.

用法

这里通过一个具体需求,一步一步来设计Builder模式

底部这个弹出框在很多页面会用到,我们就需要封装一下,叫做MenuDialog,这里使用Dialog来做(也可以用Popwindow),分析这个dialog需求,特点如下:

  • 从底部弹出,上面一行为分享组件(ShareMenu),是固定的,用于分享
  • 第二行为一些具体操作的按钮(ActionMenu),并且第二行有时候是不需要的(隐藏)
  • 考虑到扩展性,ActionMenu的个数和每一个的图标和提示语(msg)应该是可定制的
  • ShareMenu的点击事件就是调起分享,可以统一处理,ActionMenu由于具体操作不同,应该暴露给调用者自行处理
  • ActionMenu的图标和msg都应该有默认,"分享到"这个title也应该有默认并且可定制

数据存放 MenuDiaControl

在builder模式中,一般会有个存放数据的类Control,这里新建MenuDiaControl用于存放需要用到的参数

public class MenuDiaControl {
    private Context mContext;
    private String title = "分享到";
    //share
    private String mShareTitle = "";
    private String mShareContent = "";
    private String mShareImageUrl = "";
    private String mShareUrl = "";
    //action
    private boolean mHineActionAll = false;//是否隐藏action操作栏
    private List<Boolean> mBooleanList = new ArrayList<>();//单个action的按钮的图标和msg
    private MoreMenuClickListener mListener;//Action回调
    //geter and seter
}

内部类 Builder

Builder类是Builder模式中的主体操作类,接受配置参数并最后生成对象,具体实现如下:

public static class Builder {
    private final MenuDiaControl mDiaControl;//存放参数

    public Builder(Context context) {
        mDiaControl = new MenuDiaControl(context);//初始化Control
    }

    /*<====================================公开的配置方法====================================================>*/

    /**
     * 设置title 默认="分享到"
     *
     * @param title
     * @return
     */
    public Builder title(String title) {
        mDiaControl.setTitle(title);
        return this;
    }
    //更多...(具体代码在文章最后)

    /*<====================================公开的配置方法===================================================>*/

    public MenuDialog build() {//生成对象
        return new MenuDialog(mDiaControl);
    }

}

对象 MenuDialog

即我们需要通过Builder模式创建的对象,最后的产出

public class MenuDialog extends Dialog {

//ButterKnife.bind..

private ShareUtils mShare;
private MenuDiaControl mControl;
private List<TextView> mViewList = new ArrayList<>();

private MenuDialog(MenuDiaControl control) {
    this(control.getContext(), R.style.CustomDialog);
    mControl = control;
    init();
}

private MenuDialog(Context context, int themeResId) {
    super(context, themeResId);
}

private void init() {    //setContentView
    View diaView = View.inflate(mControl.getContext(), R.layout.dialog_post_operator, null);
    setContentView(diaView);
    ButterKnife.bind(this);
    initWindow();
    setContentView(diaView);
    initView();
    mShare = new ShareUtils(mControl.getContext());        //分享工具类
}

private void initView() {        //根据Control中的参数,为对象设置各种属性
    mTvTitle.setText(mControl.getTitle());
    mViewList.add(mTvBackCircleList);
    mViewList.add(mTvCopyUrl);
    mViewList.add(mTvReport);
    mViewList.add(mTvDelete);
    for (int i = 0; i < mViewList.size(); i++) {    //设置单个action
        if (mControl.getBooleanList().get(i)) mViewList.get(i).setVisibility(View.INVISIBLE);
        TextView textView = mViewList.get(i);
        MenuBean menuBean = mControl.getMenuBeanList().get(i);
        textView.setText(menuBean.getMsg());
        Drawable drawable = mControl.getContext().getResources().getDrawable(menuBean.getIconRes());
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        textView.setCompoundDrawables(null, drawable, null, null);
    }
    mLlMore.setVisibility(mControl.isHineActionAll() ? View.GONE : View.VISIBLE);//是否隐藏ActionMenu

}

public static class Builder {
    //Builder内部类...
}

private void initWindow() {    //设置window的一些属性
    setCancelable(false);
    Window window = getWindow();
    int width = LinearLayout.LayoutParams.MATCH_PARENT;
    window.setLayout(width, LinearLayout.LayoutParams.WRAP_CONTENT);
    window.setGravity(Gravity.BOTTOM);
    setCanceledOnTouchOutside(true);
}

@OnClick({R.id.tv_wechat, R.id.tv_wechat_circle, R.id.tv_qq, R.id.tv_sina, R.id.tv_back_circle_list, R.id.tv_copy_url, R.id
        .tv_report, R.id.tv_delete, R.id.btn_cancel})
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.tv_wechat:
            mShare.initShare(mControl.getShareTitle(), mControl.getShareContent(), mControl.getShareImageUrl(), mControl.getShareUrl
                    (), null);
            mShare.setPlatform(Wechat.NAME);
            mShare.startShare();
        
            break;
        //...执行统一的分享操作
        case R.id.tv_back_circle_list:    //Action具体操作回调给调用者
            if (mControl.getListener() != null)
                mControl.getListener().menuClick(0, this);
            break;
        case R.id.tv_copy_url:
            if (mControl.getListener() != null)
                mControl.getListener().menuClick(1, this);
            break;
        case R.id.tv_report:
            if (mControl.getListener() != null)
                mControl.getListener().menuClick(2, this);
            break;
        case R.id.tv_delete:
            if (mControl.getListener() != null)
                mControl.getListener().menuClick(3, this);
            break;
        case R.id.btn_cancel:
            break;
    }
    dismiss();
}
}  

使用

ok,一切都搞定后,我们看下使用方法,跟AlerterDialog的使用很像吧.我们使用Builder模式封装Menudialog,使用简单,链式调用,支持定制,在这个项目中是通用的,满足了上面的需求.

    new MenuDialog.Builder(this)
            .hideActionAll(false)//不隐藏ActionMenu
            .shareData(new ShareBean(mInfoItem.getTitle(), mInfoItem.getSummary(), mInfoItem.getTitlePic(), mInfoItem.getUrl()))//设置分享数据
            .setActionMenu(2,R.mipmap.icon,"msg")//制定ActionMenu
            .title("设置title")
            .hideAction4pos(3)//隐藏单个Action
            .build()
            //...
            .show();

总结

Builder模式设计起来很简单,大家可以大胆的用到自己的项目或者框架中.

  • Control类不是必须的,参数可以直接存放在Builder中,Android中很多Builder模式是省略Control的
  • 上面的R.style.CustomDialog主要是用来使Dialog全屏的
  • 上面的ShareBean是分享需要的参数实体
  • ShareMenu也可以提供分享是否成功的回调,提供定制,等等待完善功能...

具体:

<style name="CustomDialog" parent="@android:style/Theme.Dialog">
    <item name="android:windowFrame">@null</item>
    <!-- Dialog的windowFrame框为无 -->
    <item name="android:windowIsFloating">true</item>
    <!-- 是否浮现在activity之上 -->
    <item name="android:windowIsTranslucent">false</item>
    <!-- 是否半透明 -->
    <item name="android:windowNoTitle">true</item>
    <!-- 背景透明-->
    <item name="android:windowBackground">@color/transparent</item>
    <item name="android:backgroundDimEnabled">true</item>
</style>`

Builder类具体代码:

public static class Builder {
    private final MenuDiaControl mDiaControl;

    public Builder(Context context) {
        mDiaControl = new MenuDiaControl(context);
    }

    /*<========================================================================================>*/
    /**
     * 设置title 默认="分享到"
     *
     * @param title
     * @return
     */
    public Builder title(String title) {
        mDiaControl.setTitle(title);
        return this;
    }

    /**
     * 是否隐藏第二行的扩展操作按钮
     * 默认不隐藏
     *
     * @param hide
     * @return
     */
    public Builder hideActionAll(boolean hide) {
        mDiaControl.setHineActionAll(hide);
        return this;
    }

    public Builder shareTitle(String title) {
        mDiaControl.setShareTitle(title);
        return this;
    }

    public Builder shareContent(String shareContent) {
        mDiaControl.setShareContent(shareContent);
        return this;
    }

    public Builder shareImageUrl(String shareImageUrl) {
        mDiaControl.setShareImageUrl(shareImageUrl);
        return this;
    }

    public Builder ShareUrl(String ShareUrl) {
        mDiaControl.setShareUrl(ShareUrl);
        return this;
    }

    /**
     * 一次性设置分享需要的数据
     *
     * @param bean
     * @return
     */
    public Builder shareData(ShareBean bean) {
        mDiaControl.setShareTitle(bean.getTitle());
        mDiaControl.setShareContent(bean.getContent());
        mDiaControl.setShareImageUrl(bean.getImageUrl());
        mDiaControl.setShareUrl(bean.getUrl());
        return this;
    }

    /**
     * 设置底部某个menu的图标和msg
     *
     * @param position
     * @param iconRes
     * @param msg
     * @return
     */
    public Builder setActionMenu(int position, int iconRes, String msg) {
        if (position < 0 || position > 3) return this;
        mDiaControl.getMenuBeanList().set(position, new MenuBean(iconRes, msg, false));
        return this;
    }

    /**
     * 隐藏底部某个menu
     *
     * @param position
     * @return
     */
    public Builder hideAction4pos(int position) {
        if (position < 0 || position > 3) return this;
        mDiaControl.getBooleanList().set(position, true);
        return this;
    }

    /**
     * 底部menu的点击回调
     *
     * @param listener
     * @return
     */
    public Builder addActionMenuClick(MenuDiaControl.MoreMenuClickListener listener) {
        mDiaControl.setListener(listener);
        return this;
    }

    /*<========================================================================================>*/

    /**
     * 构造器
     *
     * @return
     */
    public MenuDialog build() {
        return new MenuDialog(mDiaControl);
    }
}

关于作者

相关文章

  • 安卓设计模式(三)Builder模式

    Builder模式也叫建造者模式,属于创建性模式,一般用于复杂对象的创建该模式可以将构建复杂对象的过程和它的部件解...

  • 安卓设计模式-构建者模式

    安卓设计模式-构建者模式 是什么 构建者模式又生builder模式,是将复杂的对象的构建与他的表示分离,使得同样的...

  • 安卓设计模式之建造者模式Builder

    Builder模式是安卓开发中一种常见的设计模式,这里我们简单介绍一下。 Builder的定义 将一个复杂对象的构...

  • 建造者模式

    安卓常用的设计模式建造者模式也被称为生成器模式,Builder模式,它是创建一个复杂对象的创建型模式,其将构建复杂...

  • 创建者设计模式

    Builder -创建者设计模式 是一种非常常见的设计模式,在安卓源码和第三方组件中经常可以见到: 边学编写 我将...

  • 安卓设计模式(二)单例模式

    单例模式是使用最广的设计模式,也是大家最为熟知的. 该系列其他文章: 安卓设计模式(一)面向对象六大设计原则 安卓...

  • AlertDialog中的Builder模式

    序言 AlertDialog是安卓系统中常用的对话框,它采用Builder设计模式,将对话框的创建和表现显示分离。...

  • Java 十一种设计模式深入理解

    目录一、工厂设计模式二、抽象工厂模式三、单例设计模式四、建造者(Builder)模式五、原型模式六、适配器设计模式...

  • Android 设计模式demo项目

    Android 设计模式demo项目 安卓各种设计模式demoGitHub地址android-design-pat...

  • Android 设计模式之简单工厂模式

    设计模式系列文章 Android 设计模式之单例模式 Android 设计模式之Builder模式 Android...

网友评论

    本文标题:安卓设计模式(三)Builder模式

    本文链接:https://www.haomeiwen.com/subject/drorettx.html