在Android中探秘建造者模式
2015-06-06 16:34
393 查看
前言
在Android开发过程中,我发现很多安卓源代码里应用了设计模式,比较常用的有适配器模式(各种adapter),建造者模式(Alert Dialog的构建)等等。虽然我们对大多数设计模式都有所了解,但是在应用设计模式的这个方面,感觉很多人在这方面有所不足。所以,我们可以看看Android源代码里面是怎样实现各种设计模式的,从而可以加深我们对设计模式的理解,从而方便我们以后对它的应用。今天,我们就来谈谈设计者模式(Builder Pattern)。定义
建造者模式(Builder Pattern)也叫做生成器模式,其定义如下:Separate the construction of a complex object from its representation so that the same construction process can create different representions. 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
它的意思就是将一个对象和怎么构建这个对象分离开来,如果你想构建一个对象,你把这个消息告诉构建者,并且将自己对这个对象的各种要求告诉建造者,然后建造者根据这些要求进行捣鼓,然后,你所需要的一个对象就出来了。
Android源代码AlertDialog的实现
我们先来看下AlertDialog的源代码(只列出关键代码):public class AlertDialog extends Dialog implements DialogInterface { ... protected AlertDialog(Context context, int theme) { this(context, theme, true); } AlertDialog(Context context, int theme, boolean createThemeContextWrapper) { super(context, resolveDialogTheme(context, theme), createThemeContextWrapper); mWindow.alwaysReadCloseOnTouchAttr(); mAlert = new AlertController(getContext(), this, getWindow()); } protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) { super(context, resolveDialogTheme(context, 0)); mWindow.alwaysReadCloseOnTouchAttr(); setCancelable(cancelable); setOnCancelListener(cancelListener); mAlert = new AlertController(context, this, getWindow()); } public static class Builder { private final AlertController.AlertParams P; private int mTheme; 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; } public Builder setMessage(CharSequence message) { P.mMessage = message; return this; } public AlertDialog create() { final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false); P.apply(dialog.mAlert); dialog.setCancelable(P.mCancelable); if (P.mCancelable) { dialog.setCanceledOnTouchOutside(true); } dialog.setOnCancelListener(P.mOnCancelListener); dialog.setOnDismissListener(P.mOnDismissListener); if (P.mOnKeyListener != null) { dialog.setOnKeyListener(P.mOnKeyListener); } return dialog; } ... } }
从上面我们可以清楚地看到:AlertDialog的Build是一个静态内部类(在有些情况下,我们会单独定义一个Build抽象类,然后用具体类来继承它,实现具体的功能)。我们对AlertDialog设置的属性会暂时保存在Build类的成员变量P(AlertController.AlertParams)中。同时,我们注意到我们设置的属性,它都回返回本身的AlertBuild对象,这样我们就可以不停地调用它设置的方法。
如果我们想获得这个AlertDialog。我们就需要调用建造者的create()方法,在create()方法里面它就会构造出一个Dialog实例,并且将我们刚才设置的属性全部赋给AlertDialog,最后返回AlertDialog的实例。
UniversalImageLoader上面建造者的实现
看完了AlertDialog,我们这边再看一个实例,那就是Android开源框架UniversalImageLoader的DisplayImageOptions类,下面是它的一些核心代码:public final class DisplayImageOptions { private final int imageResOnLoading; private final int imageResForEmptyUri; private final int imageResOnFail; private final Drawable imageOnLoading; private final Drawable imageForEmptyUri; private final Drawable imageOnFail; private final boolean resetViewBeforeLoading; private final boolean cacheInMemory; private final boolean cacheOnDisk; private final ImageScaleType imageScaleType; private final Options decodingOptions; private final int delayBeforeLoading; private final boolean considerExifParams; private final Object extraForDownloader; private final BitmapProcessor preProcessor; private final BitmapProcessor postProcessor; private final BitmapDisplayer displayer; private final Handler handler; private final boolean isSyncLoading; private DisplayImageOptions(Builder builder) { imageResOnLoading = builder.imageResOnLoading; imageResForEmptyUri = builder.imageResForEmptyUri; imageResOnFail = builder.imageResOnFail; imageOnLoading = builder.imageOnLoading; imageForEmptyUri = builder.imageForEmptyUri; imageOnFail = builder.imageOnFail; resetViewBeforeLoading = builder.resetViewBeforeLoading; cacheInMemory = builder.cacheInMemory; cacheOnDisk = builder.cacheOnDisk; imageScaleType = builder.imageScaleType; decodingOptions = builder.decodingOptions; delayBeforeLoading = builder.delayBeforeLoading; considerExifParams = builder.considerExifParams; extraForDownloader = builder.extraForDownloader; preProcessor = builder.preProcessor; postProcessor = builder.postProcessor; displayer = builder.displayer; handler = builder.handler; isSyncLoading = builder.isSyncLoading; } ... public static class Builder { private int imageResOnLoading = 0; private int imageResForEmptyUri = 0; private int imageResOnFail = 0; private Drawable imageOnLoading = null; private Drawable imageForEmptyUri = null; private Drawable imageOnFail = null; private boolean resetViewBeforeLoading = false; private boolean cacheInMemory = false; private boolean cacheOnDisk = false; private ImageScaleType imageScaleType = ImageScaleType.IN_SAMPLE_POWER_OF_2; private Options decodingOptions = new Options(); private int delayBeforeLoading = 0; private boolean considerExifParams = false; private Object extraForDownloader = null; private BitmapProcessor preProcessor = null; private BitmapProcessor postProcessor = null; private BitmapDisplayer displayer = DefaultConfigurationFactory.createBitmapDisplayer(); private Handler handler = null; private boolean isSyncLoading = false; public Builder() { decodingOptions.inPurgeable = true; decodingOptions.inInputShareable = true; } /** * Stub image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware * image aware view} during image loading * * @param imageRes Stub image resource * @deprecated Use {@link #showImageOnLoading(int)} instead */ @Deprecated public Builder showStubImage(int imageRes) { imageResOnLoading = imageRes; return this; } /** * Incoming image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware * image aware view} during image loading * * @param imageRes Image resource */ public Builder showImageOnLoading(int imageRes) { imageResOnLoading = imageRes; return this; } /** Builds configured {@link DisplayImageOptions} object */ public DisplayImageOptions build() { return new DisplayImageOptions(this); } ... } }
它比AlertDialog实现更为简单一点,直接将属性定义在Builder的成员变量中,然后将Builder对象返回给DisplayImageOptions中直接进行赋值,这样做的话,将初始化对象的复杂逻辑全部交给了Builder类,而使我们需要的DisplayImageOptions显得非常的干净,功能也相当的简洁明了
相关文章推荐
- Android 广播的生命周期
- Android系统中的广播(Broadcast)机制简要介绍和学习计划
- 【转】Android 平台下使用 i2c-tools
- Android中Bitmap和Drawable
- 关于Fragment API版本兼容问题
- 1第一个Android应用程序
- android百度地图定位,点击给定经纬度的某点进行弹窗
- androidstudio中出现Rendering Problems,字体太小,显示不了组件问题
- 安卓showTime and showDate 两个按钮,并在xml中写入相应的onClick方法
- Android之NDK开发
- Android 部分属性学习
- Android 学习笔记 Service服务与远程通信...(AIDL)
- 技术总结--android篇(二)--布局的优化
- Android平台中获取状态栏的高度代码实现
- (二)Android导航栏和菜单资源的结合使用
- 技术总结--android篇(一)--MVC模式
- Android之Windows下生成动态库so并打包到APK中(转)
- Android串口操作,简化android-serialport-api的demo(转)
- Android实战简易教程-第十一枪(树形组件:ExpandableListView显示和动态添加删除)
- <Android>inflate的方法参数说明