Android 设计模式学习之 Builder 模式
来源:互联网 发布:mac vpn 没有pptp 编辑:程序博客网 时间:2024/04/28 06:16
新媒体管家
点击上方“程序员大咖”,选择“置顶公众号”
关键时刻,第一时间送达!
Android 设计模式学习之观察者模式
建造者模式(Builder Pattern),是创造性模式之一,Builder 模式的目的则是为了将对象的构建与展示分离。Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程。
模式的使用场景
相同的方法,不同的执行顺序,产生不同的事件结果时;
多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时;
产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适。
UML类图
角色介绍
Product 产品类 : 产品的抽象类;
Builder : 抽象类, 规范产品的组建,一般是由子类实现具体的组件过程;
ConcreteBuilder : 具体的构建器;
Director : 统一组装过程(可省略)。
Builder模式简单实现
Builder模式最典型的例子,就是组装电脑的例子了 。
创建产品类
创建Builder类
组装电脑有一套组装方法的模版,就是一个抽象的Builder类,里面提供了安装CPU、内存的方法,以及组装成电脑的create方法:
实现了抽象的Builder类,ComputerBuilder类用于组装电脑:
用Dirextor指挥者类来统一组装过程
客户端调用指挥者类
最后商家用指挥者类组装电脑。我们只需要提供我们想要的CPU,内存就可以了,至于商家怎样组装的电脑我们无需知道。
Android源码中的Builder模式
在Android源码中,我们最常用到的Builder模式就是AlertDialog.Builder, 使用该Builder来构建复杂的AlertDialog对象。简单示例如下 :
下面我们看看AlertDialog的相关源码
// AlertDialog
public class AlertDialog extends Dialog implements DialogInterface {
// Controller, 接受Builder成员变量P中的各个参数 private AlertController mAlert;
// 构造函数 protected AlertDialog(Context context, int theme) {
this(context, theme, true); }
// 4 : 构造AlertDialog AlertDialog(Context context, int theme, boolean createContextWrapper) { super(context, resolveDialogTheme(context, theme), createContextWrapper); mWindow.alwaysReadCloseOnTouchAttr(); mAlert = new AlertController(getContext(), this, getWindow()); }
// 实际上调用的是mAlert的setTitle方法 @Override public void setTitle(CharSequence title) { super.setTitle(title); mAlert.setTitle(title); }
// 实际上调用的是mAlert的setCustomTitle方法 public void setCustomTitle(View customTitleView) { mAlert.setCustomTitle(customTitleView); } public void setMessage(CharSequence message) { mAlert.setMessage(message); }
// AlertDialog其他的代码省略 // ************ Builder为AlertDialog的内部类 ******************* public static class Builder {
// 1 : 存储AlertDialog的各个参数, 例如title, message, icon等. private final AlertController.AlertParams P;
// 属性省略 /** * Constructor using a context for this builder and the {@link AlertDialog} it creates. */ public Builder(Context context) {
this(context, resolveDialogTheme(context, 0)); } public Builder(Context context, int theme) { P = new AlertController.AlertParams(new ContextThemeWrapper( context, resolveDialogTheme(context, theme))); mTheme = theme; }
// Builder的其他代码省略 ...... // 2 : 设置各种参数 public Builder setTitle(CharSequence title) { P.mTitle = title;
return this; } public Builder setMessage(CharSequence message) { P.mMessage = message;
return this; } public Builder setIcon(int iconId) { P.mIconId = iconId;
return this; } public Builder setPositiveButton(CharSequence text, final OnClickListener listener) { P.mPositiveButtonText = text; P.mPositiveButtonListener = listener;
return this; } public Builder setView(View view) { P.mView = view; P.mViewSpacingSpecified = false;
return this; }
// 3 : 构建AlertDialog, 传递参数 public AlertDialog create() {
// 调用new AlertDialog构造对象, 并且将参数传递个体AlertDialog final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
// 5 : 将P中的参数应用的dialog中的mAlert对象中 P.apply(dialog.mAlert); dialog.setCancelable(P.mCancelable);
if (P.mCancelable) { dialog.setCanceledOnTouchOutside(true); } dialog.setOnCancelListener(P.mOnCancelListener);
if (P.mOnKeyListener != null) { dialog.setOnKeyListener(P.mOnKeyListener); }
return dialog; } }}
可以看到,通过Builder来设置AlertDialog中的title, message, button等参数, 这些参数都存储在类型为AlertController.AlertParams的成员变量P中,AlertController.AlertParams中包含了与之对应的成员变量。在调用Builder类的create函数时才创建AlertDialog, 并且将Builder成员变量P中保存的参数应用到AlertDialog的mAlert对象中,即P.apply(dialog.mAlert)代码段。我们看看apply函数的实现 :
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); }
if (mPositiveButtonText != null) { dialog.setButton(DialogInterface.BUTTON_POSITIVE, mPositiveButtonText, mPositiveButtonListener, null); }
if (mNegativeButtonText != null) { dialog.setButton(DialogInterface.BUTTON_NEGATIVE, mNegativeButtonText, mNegativeButtonListener, null); }
if (mNeutralButtonText != null) { dialog.setButton(DialogInterface.BUTTON_NEUTRAL, mNeutralButtonText, mNeutralButtonListener, null); }
if (mForceInverseBackground) { dialog.setInverseBackgroundForced(true); }
// For a list, the client can either supply an array of items or an // adapter or a cursor if ((mItems != null) || (mCursor != null) || (mAdapter != null)) { createListView(dialog); }
if (mView != null) {
if (mViewSpacingSpecified) { dialog.setView(mView, mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight, mViewSpacingBottom); } else { dialog.setView(mView); } } }
实际上就是把P中的参数挨个的设置到AlertController中, 也就是AlertDialog中的mAlert对象。从AlertDialog的各个setter方法中我们也可以看到,实际上也都是调用了mAlert对应的setter方法。在这里,Builder同时扮演了上文中提到的builder、ConcreteBuilder、Director的角色,简化了Builder模式的设计。
在实际项目中的应用
我们可以采用系统已经提供好的Builder设计模式构建整个应用的万能Dialog,代码可以参考系统的AlertDialog
public static class Builder { private AlertController.AlertParams P; public Builder(Context context) {
this(context, 0); } public Builder(Context context, int themeResId) { P = new AlertController.AlertParams(); P.themeResId = themeResId; P.context = context; } public Builder setText(int viewId, CharSequence text) { P.textArray.put(viewId, text);
return this; } public Builder setOnClickListener(int viewId, View.OnClickListener listener) { P.clickArray.put(viewId, listener);
return this; } public Builder setContentView(int layoutId) { P.view = null; P.layoutId = layoutId;
return this; } public Builder setContentView(View view) { P.layoutId = 0; P.view = view;
return this; }
/** * Sets whether the dialog is cancelable or not. Default is true. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setCancelable(boolean cancelable) { P.cancelable = cancelable;
return this; }
/** * Sets the callback that will be called if the dialog is canceled. * <p> * <p>Even in a cancelable dialog, the dialog may be dismissed for reasons other than * being canceled or one of the supplied choices being selected. * If you are interested in listening for all cases where the dialog is dismissed * and not just when it is canceled, see * {@link #setOnDismissListener(OnDismissListener) setOnDismissListener}.</p> * * @return This Builder object to allow for chaining of calls to set methods * @see #setCancelable(boolean) * @see #setOnDismissListener(OnDismissListener) */ public Builder setOnCancelListener(OnCancelListener onCancelListener) { P.onCancelListener = onCancelListener;
return this; }
/** * Sets the callback that will be called when the dialog is dismissed for any reason. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setOnDismissListener(OnDismissListener onDismissListener) { P.onDismissListener = onDismissListener;
return this; }
/** * Sets the callback that will be called if a key is dispatched to the dialog. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setOnKeyListener(OnKeyListener onKeyListener) { P.onKeyListener = onKeyListener;
return this; }
/** * Creates an {@link AlertDialog} with the arguments supplied to this * builder. * <p/> * Calling this method does not display the dialog. If no additional * processing is needed, {@link #show()} may be called instead to both * create and display the dialog. */ public BaseDialog create() {
// Context has already been wrapped with the appropriate theme. final BaseDialog dialog = new BaseDialog(P.context, P.themeResId); P.apply(dialog.mAlert); dialog.setCancelable(P.cancelable);
if (P.cancelable) { dialog.setCanceledOnTouchOutside(true); } dialog.setOnCancelListener(P.onCancelListener); dialog.setOnDismissListener(P.onDismissListener);
if (P.onKeyListener != null) { dialog.setOnKeyListener(P.onKeyListener); }
return dialog; }
/** * Creates an {@link AlertDialog} with the arguments supplied to this * builder and immediately displays the dialog. * <p/> * Calling this method is functionally identical to: * <pre> * AlertDialog dialog = builder.create(); * dialog.show(); * </pre> */ public BaseDialog show() { final BaseDialog dialog = create(); dialog.show();
return dialog; } }
class AlertController { private DialogViewHelper mViewHelper; private BaseDialog mDialog; private Window mWindow; public AlertController(BaseDialog dialog, Window window) { mDialog = dialog; mWindow = window; }
/** * 获取Dialog * @return */ public BaseDialog getDialog() {
return mDialog; }
/** * 获取window * @return */ public Window getWindow() {
return mWindow; } public DialogViewHelper getViewHelper() {
return mViewHelper; }
/** * 设置View的辅助 * @param viewHelper */ public void setDialogViewHelper(DialogViewHelper viewHelper) {
this.mViewHelper = viewHelper; }
/** * 设置文本 * @param viewId * @param text */ public void setText(int viewId, CharSequence text) { mViewHelper.setText(viewId, text); }
/** * 设置点击事件 * @param viewId * @param listener */ public void setOnClickListener(int viewId, View.OnClickListener listener) { mViewHelper.setOnClickListener(viewId, listener); }
/** * 通过id获取View * @param viewId * @param <T> * @return */ public <T extends View> T getView(int viewId) {
return mViewHelper.getView(viewId); }}
代码调用
@Override public void onClick(View v) { BaseDialog dialog = new BaseDialog.Builder(this) .setContentView(R.layout.detail_dialog).fullWith() .fromBottom(false) .show(); }
最后总结一下Buider模式的优缺点:
Builder 模式的优点:
1.将一个复杂对象的创建过程封装起来,使得客户端不必知道产品内部组成的细节;
2.允许对象通过多个步骤来创建,并且可以改变过程和选择需要的过程;
3.产品的实现可以被替换,因为客户端只看到一个抽象的接口;
创建者独立,容易扩展。
Builder 模式缺点:
1.会产生多余的 Builder 对象以及 Director 对象,消耗内存;
2.与工厂模式相比,采用 Builder 模式创建对象的客户,需要具备更多的领域知识。
来自:CSDN-马云龙
http://blog.csdn.net/u012124438/article/details/59777619
程序员大咖整理发布,转载请联系作者获得授权
【点击成为安卓大神】
- Android设计模式学习之Builder模式
- Android 设计模式学习之 Builder 模式
- Android设计模式之Builder
- Android设计模式之Builder
- android设计模式之builder
- 设计模式之Builder模式学习
- 设计模式学习之Builder模式
- Android设计模式之Builder模式
- 《Android源码设计模式》之Builder模式
- Android 设计模式之Builder模式
- Android设计模式之—Builder模式
- 设计模式学习--Builder
- 设计模式之Builder
- 设计模式之Builder
- 设计模式之Builder
- 设计模式之Builder
- 设计模式之Builder
- 设计模式之Builder
- 自定义vector类(数据结构与算法C++)
- 包罗万象
- php-refactoring-browser, PHP的命令行 重构工具
- 上下左右中布局
- mysql查询操作
- Android 设计模式学习之 Builder 模式
- C语言实验——分数序列
- Android读书笔记(十) Glide、下拉刷新、全局获取Context
- 轻松学习 JavaScript——第 2 部分:函数中的 Rest 参数
- 论改别人代码
- 定了!国家公布人工智能重磅消息,这些人将集体失业....
- 积极推动发展和制造商沟通交流
- Unity Shader 学习笔记(24) 深度纹理、法线纹理
- IO文件读写与复制