Android设计模式学习之Builder模式

2024-06-24 05:32

本文主要是介绍Android设计模式学习之Builder模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android设计模式学习之观察者模式

建造者模式(Builder Pattern),是创造性模式之一,Builder 模式的目的则是为了将对象的构建与展示分离。Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程。

模式的使用场景

1.相同的方法,不同的执行顺序,产生不同的事件结果时;
2.多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时;
3.产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适。

UML类图

这里写图片描述

角色介绍

Product 产品类 : 产品的抽象类;
Builder : 抽象类, 规范产品的组建,一般是由子类实现具体的组件过程;
ConcreteBuilder : 具体的构建器;
Director : 统一组装过程(可省略)。

Builder模式简单实现

Builder模式最典型的例子,就是组装电脑的例子了
创建产品类

public class Computer {private String mCpu;private String mRam;public void setmCpu(String mCpu) {this.mCpu = mCpu;}public void setmRam(String mRam) {this.mRam = mRam;}
}

创建Builder类
组装电脑有一套组装方法的模版,就是一个抽象的Builder类,里面提供了安装CPU、内存的方法,以及组装成电脑的create方法:

public abstract class Builder {public abstract void buildCpu(String cpu);public abstract void buildRam(String ram);public abstract Computer create();
}

实现了抽象的Builder类,ComputerBuilder类用于组装电脑:

public class ComputerBuilder extends Builder {private Computer mComputer = new Computer();@Overridepublic void buildCpu(String cpu) {mComputer.setmCpu(cpu);}@Overridepublic void buildRam(String ram) {mComputer.setmRam(ram);}@Overridepublic Computer create() {return mComputer;}
}

用Dirextor指挥者类来统一组装过程

public class Direcror {Builder mBuild=null;public Direcror(Builder build){this.mBuild=build;}public Computer CreateComputer(String cpu,String mainboard,String ram){//规范建造流程this.mBuild.buildMainboard(mainboard);     this.mBuild.buildRam(ram);return mBuild.create();}
}

客户端调用指挥者类

最后商家用指挥者类组装电脑。我们只需要提供我们想要的CPU,内存就可以了,至于商家怎样组装的电脑我们无需知道。

public class CreatComputer {public static void main(String[]args){Builder mBuilder=new MoonComputerBuilder();Direcror mDirecror=new Direcror(mBuilder);//组装电脑mDirecror.CreateComputer("i5-3210","DDR4");}
}

Android源码中的Builder模式

在Android源码中,我们最常用到的Builder模式就是AlertDialog.Builder, 使用该Builder来构建复杂的AlertDialog对象。简单示例如下 :

   //显示基本的AlertDialog  private void showDialog(Context context) {  AlertDialog.Builder builder = new AlertDialog.Builder(context);  builder.setIcon(R.drawable.icon);  builder.setTitle("头部");  builder.setMessage("内容");  builder.setPositiveButton("Button1",  new DialogInterface.OnClickListener() {  public void onClick(DialogInterface dialog, int whichButton) {  setTitle("点击了对话框上的Button1");  }  }).setNeutralButton("Button2",  new DialogInterface.OnClickListener() {  public void onClick(DialogInterface dialog, int whichButton) {  setTitle("点击了对话框上的Button2");  }  });  builder.create().show();  // 构建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 : 构造AlertDialogAlertDialog(Context context, int theme, boolean createContextWrapper) {super(context, resolveDialogTheme(context, theme), createContextWrapper);mWindow.alwaysReadCloseOnTouchAttr();mAlert = new AlertController(getContext(), this, getWindow());}// 实际上调用的是mAlert的setTitle方法@Overridepublic 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 cursorif ((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);}
}

代码调用

  @Overridepublic 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 模式创建对象的客户,需要具备更多的领域知识。

这篇关于Android设计模式学习之Builder模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1089289

相关文章

51单片机学习记录———定时器

文章目录 前言一、定时器介绍二、STC89C52定时器资源三、定时器框图四、定时器模式五、定时器相关寄存器六、定时器练习 前言 一个学习嵌入式的小白~ 有问题评论区或私信指出~ 提示:以下是本篇文章正文内容,下面案例可供参考 一、定时器介绍 定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。 定时器作用: 1.用于计数系统,可

问题:第一次世界大战的起止时间是 #其他#学习方法#微信

问题:第一次世界大战的起止时间是 A.1913 ~1918 年 B.1913 ~1918 年 C.1914 ~1918 年 D.1914 ~1919 年 参考答案如图所示

[word] word设置上标快捷键 #学习方法#其他#媒体

word设置上标快捷键 办公中,少不了使用word,这个是大家必备的软件,今天给大家分享word设置上标快捷键,希望在办公中能帮到您! 1、添加上标 在录入一些公式,或者是化学产品时,需要添加上标内容,按下快捷键Ctrl+shift++就能将需要的内容设置为上标符号。 word设置上标快捷键的方法就是以上内容了,需要的小伙伴都可以试一试呢!

AssetBundle学习笔记

AssetBundle是unity自定义的资源格式,通过调用引擎的资源打包接口对资源进行打包成.assetbundle格式的资源包。本文介绍了AssetBundle的生成,使用,加载,卸载以及Unity资源更新的一个基本步骤。 目录 1.定义: 2.AssetBundle的生成: 1)设置AssetBundle包的属性——通过编辑器界面 补充:分组策略 2)调用引擎接口API

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

大学湖北中医药大学法医学试题及答案,分享几个实用搜题和学习工具 #微信#学习方法#职场发展

今天分享拥有拍照搜题、文字搜题、语音搜题、多重搜题等搜题模式,可以快速查找问题解析,加深对题目答案的理解。 1.快练题 这是一个网站 找题的网站海量题库,在线搜题,快速刷题~为您提供百万优质题库,直接搜索题库名称,支持多种刷题模式:顺序练习、语音听题、本地搜题、顺序阅读、模拟考试、组卷考试、赶快下载吧! 2.彩虹搜题 这是个老公众号了 支持手写输入,截图搜题,详细步骤,解题必备

如何开启和关闭3GB模式

https://jingyan.baidu.com/article/4d58d5414dfc2f9dd4e9c082.html

《offer来了》第二章学习笔记

1.集合 Java四种集合:List、Queue、Set和Map 1.1.List:可重复 有序的Collection ArrayList: 基于数组实现,增删慢,查询快,线程不安全 Vector: 基于数组实现,增删慢,查询快,线程安全 LinkedList: 基于双向链实现,增删快,查询慢,线程不安全 1.2.Queue:队列 ArrayBlockingQueue:

十五.各设计模式总结与对比

1.各设计模式总结与对比 1.1.课程目标 1、 简要分析GoF 23种设计模式和设计原则,做整体认知。 2、 剖析Spirng的编程思想,启发思维,为之后深入学习Spring做铺垫。 3、 了解各设计模式之间的关联,解决设计模式混淆的问题。 1.2.内容定位 1、 掌握设计模式的"道" ,而不只是"术" 2、 道可道非常道,滴水石穿非一日之功,做好长期修炼的准备。 3、 不要为了

十四、观察者模式与访问者模式详解

21.观察者模式 21.1.课程目标 1、 掌握观察者模式和访问者模式的应用场景。 2、 掌握观察者模式在具体业务场景中的应用。 3、 了解访问者模式的双分派。 4、 观察者模式和访问者模式的优、缺点。 21.2.内容定位 1、 有 Swing开发经验的人群更容易理解观察者模式。 2、 访问者模式被称为最复杂的设计模式。 21.3.观察者模式 观 察 者 模 式 ( Obser