查看原文
其他

Android 设计模式之Builder模式的简单使用

2017-02-15 陈智 一起众创



Android 设计模式之Builder模式的简单使用

一、Builder模式介绍

Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下。可以精细地控制对象的构造流程。Builder模式将复杂对象的构建过程和他的部件解耦,使得构建过程和部件的表示隔离开来。

二、使用场景

  1. 相同的方法,但是有不同的执行顺序,产生了不同的结果

  2. 多个零件和部件都可以装配到一个对象中,但是产生的运行结果不同

  3. 初始化对象复杂,但是有很多默认的参数

三、结构图

  1. Builder-抽象Builder类,规范产品的组建,一般是由子类实现具体的组建过程

  2. ConcreteBuilder-具体的Builder类

  3. Director-统一组装的过程

四、交互过程

client通过调用Director来创建不同的属性的对象,Director调用ConcreateBuilder创建所需属性的对象。层层封装,最终留给用户的只是一个调用的方法 Directo 

五、简单的使用封装

下面是我使用Builder模式对Android AlertDialog的封装

在对象中调用,通过创建构造函数并调用showDialog()方法开启创建

final MyOwnAlertDialog myOwnAlertDialog = new MyOwnAlertDialog(context, activity, title, null, "确定", "取消");  myOwnAlertDialog.setOnDiaLogListener(new MyOwnAlertDialog.OnDialogListener() {                        @Override                        public void dialogPositiveListener(View customView, DialogInterface dialogInterface, int which) {                                //dosomthing                            }                                    @Override                            public void error(String msg) {                                //dosomthing                            }                            });                        }                        @Override                        public void dialogNegativeListener(View customView, DialogInterface dialogInterface, int which) {                        }                    }).showDialog();                }            }        });

构造器Builder,是构造一个使用Builder接口的对象:通过new CustomDialog.Builder 来创建对话框对象,并调用builder里的方法设置参数,创建一个一个的ConcreteBuilder产品

public class MyOwnAlertDialog {    private Activity activity;    private String dialogMessage;    private String dialogTitle;    private String positiveText;    private String negativeText;    private View dialogView;    private int customeLayoutId;    private Context context;    private OnDialogListener listener;    private CustomDialog.Builder dialog;    //带有自定义view的构造器    public MyOwnAlertDialog(Context context, Activity activity, int customeLayoutId, String dialogTitle, String positiveText, String negativeText) {        this.context = context;        this.activity = activity;        this.customeLayoutId = customeLayoutId;        this.dialogTitle = dialogTitle;        this.positiveText = positiveText;        this.negativeText = negativeText;        this.dialogView = View.inflate(context, customeLayoutId, null);    }    //不带自定义view的构造器,    public MyOwnAlertDialog(Context context, Activity activity, String dialogMessage, String dialogTitle, String positiveText, String negativeText) {        this.context = context;        this.activity = activity;        this.dialogTitle = dialogTitle;        this.dialogMessage = dialogMessage;        this.positiveText = positiveText;        this.negativeText = negativeText;    }    public void showDialog() {        dialog = new CustomDialog.Builder(context, activity);        dialog.setTitle(dialogTitle);//设置标题        //注意:dialogMessage和dialogView是互斥关系也就是dialogMessage存在dialogView就不存在,dialogView不存在dialogMessage就存在        if (dialogMessage != null) {            dialog.setMessage(dialogMessage);//设置对话框内容        } else {            dialog.setContentView(dialogView);//设置对话框的自定义view对象        }        /**         * 尽管有两个点击事件监听器,可以通过我们自定义的监听器设置一个标记变量,从而可以实现将两个点击事件合并成一个         * 监听器OnDialogListener         * */        //确定意图传入positive标记值        dialog.setPositiveButton(positiveText, new DialogInterface.OnClickListener() {            @Override            public void onClick(DialogInterface dialogInterface, int which) {                dialogInterface.dismiss();                if (listener != null) {                    listener.dialogPositiveListener(dialogView, dialogInterface, which);                }            }            //取消意图传入negative标记值        }).setNegativeButton(negativeText, new DialogInterface.OnClickListener() {            @Override            public void onClick(DialogInterface dialogInterface, int which) {                dialogInterface.dismiss();                if (listener != null) {                    listener.dialogNegativeListener(dialogView, dialogInterface, which);                }            }        }).create().show();    }    //注册监听器方法    public MyOwnAlertDialog setOnDiaLogListener(OnDialogListener listener) {        this.listener = listener;        return this;//把当前对象返回,用于链式编程    }    //定义一个监听器接口    public interface OnDialogListener {        //customView 这个参数需要注意就是如果没有自定义view,那么它则为null        public void dialogPositiveListener(View customView, DialogInterface dialogInterface, int which);        public void dialogNegativeListener(View customView, DialogInterface dialogInterface, int which);    } }

ConcreteBuilder构建,基础的ConcreteBuilder,定义个体的方法

/** * 建造者模式封装自定义dialog * Created by david on 2016/12/21. */public class CustomDialog extends Dialog {    private static CustomDialog dialog;    public CustomDialog(Context context) {        super(context);    }    public CustomDialog(Context context, int themeResId) {        super(context, themeResId);    }    public static class Builder{        private  Activity activity;        private Context context;        private String message;        private String title;        private View contentView;        private String positiveButtonText;        private String negativeButtonText;        private OnClickListener positiveButtonClickListener;        private OnClickListener negativeButtonClickListener;        public Builder(Context context, Activity activity) {            this.context = context;            this.activity = activity;        }        public Builder setMessage(String message) {            this.message = message;            return this;        }        public Builder setMessage(int message) {            this.message = (String) context.getText(message);            return this;        }        public Builder setTitle(int title) {            this.title = (String) context.getText(title);            return this;        }        public Builder setTitle(String title) {            this.title = title;            return this;        }        public Builder setContentView(View v) {            this.contentView = v;            return this;        }        public Builder setPositiveButton(int positiveButtonText,                                         OnClickListener listener) {            this.positiveButtonText = (String) context                    .getText(positiveButtonText);            this.positiveButtonClickListener = listener;            return this;        }        public Builder setPositiveButton(String positiveButtonText,                                         OnClickListener listener) {            this.positiveButtonText = positiveButtonText;            this.positiveButtonClickListener = listener;            return this;        }        public Builder setNegativeButton(int negativeButtonText,                                         OnClickListener listener) {            this.negativeButtonText = (String) context                    .getText(negativeButtonText);            this.negativeButtonClickListener = listener;            return this;        }        public Builder setNegativeButton(String negativeButtonText,                                         OnClickListener listener) {            this.negativeButtonText = negativeButtonText;            this.negativeButtonClickListener = listener;            return this;        }        public CustomDialog create() {            LayoutInflater inflater = (LayoutInflater) context                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);            // instantiate the dialog with the custom Theme            dialog = new CustomDialog(context,R.style.Dialog);            View layout = inflater.inflate(R.layout.myownalertdialog_layout, null);            dialog.addContentView(layout, new ViewGroup.LayoutParams(                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));            DisplayMetrics dm = new DisplayMetrics();            //设置窗体大小            activity.getWindowManager().getDefaultDisplay().getMetrics(dm);            int screenWidth = dm.widthPixels;            int screenHeigh = dm.heightPixels;            int heigh = screenHeigh * 7 / 30;            int weight = screenWidth * 6 / 8;            android.view.Window window = dialog.getWindow();            window.setLayout(weight, heigh);            window.setBackgroundDrawableResource(R.drawable.dialog_shape);            // set the dialog title            //((TextView) layout.findViewById(R.id.title)).setText(title);            // set the confirm button            if (positiveButtonText != null) {                ((TextView) layout.findViewById(R.id.sure))                        .setText(positiveButtonText);                if (positiveButtonClickListener != null) {                    ((TextView) layout.findViewById(R.id.sure))                            .setOnClickListener(new View.OnClickListener() {                                public void onClick(View v) {                                    positiveButtonClickListener.onClick(dialog,                                            DialogInterface.BUTTON_POSITIVE);                                }                            });                }            } else {                // if no confirm button just set the visibility to GONE               /* layout.findViewById(R.id.back).setVisibility(                        View.GONE);*/            }            // set the cancel button            if (negativeButtonText != null) {                ((TextView) layout.findViewById(R.id.cancle))                        .setText(negativeButtonText);                if (negativeButtonClickListener != null) {                    ((TextView) layout.findViewById(R.id.cancle))                            .setOnClickListener(new View.OnClickListener() {                                public void onClick(View v) {                                    negativeButtonClickListener.onClick(dialog,                                            DialogInterface.BUTTON_NEGATIVE);                                }                            });                }            } else {                // if no confirm button just set the visibility to GONE               /* layout.findViewById(R.id.cancle).setVisibility(                        View.GONE);*/            }            // set the content message            if (message != null) {                ((TextView) layout.findViewById(R.id.alert2_title)).setText(message);            } else if (contentView != null) {                // if no message set                // add the contentView to the dialog body                ((LinearLayout) layout.findViewById(R.id.content))                        .removeAllViews();                ((LinearLayout) layout.findViewById(R.id.content)).addView(                        contentView, new ActionBar.LayoutParams(                                ViewGroup.LayoutParams.FILL_PARENT,                                ViewGroup.LayoutParams.FILL_PARENT));            }            dialog.setContentView(layout);            return dialog;        }    } }

上述示例中,通过具体的CustomDialog来封装具体的内容,通过MyOwnAlertDialog来构建具体的对象,他们一起将一个复杂对象的构建和他的表示分离,使得同样的构建过程可以创建不同的对象

六、总结

Builder模式在各类开发中都比较常见,通常作为配置类的构建器将配置的构建和表示分离开来,同时也是将配置从目标类分离出来,避免过多的方法, 有良好的封装性,使得代码易修改,独立,容易扩展


React/React-Native/Flux/Redux/跨平台项目实战 6天魔鬼训练


扫描二维码

关注更多精彩



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存