Android开发笔记(九十一)工厂模式
2016-04-22 17:00
459 查看
基本概念
工厂模式是一种常用的实例化对象设计模式。程序开发很多时候都在不停地敲if、else,因为业务需求总在发展变化,今天客户要求生产A产品,明天客户要求把A产品稍微改改变成B产品,当然A产品与B产品的基本特性差不多,只在某些细节上存在差异。可是这样推陈出新就害苦了程序员,每次变动都得加上一堆的if、else,而且随着产品数量变多,程序代码也越来越难以维护。
工厂模式的出现便是要解决这种困惑,它把产品制造分为两种参与对象,第一种是制造出来的产品,第二种是负责制造的工厂。各产品肯定要进行抽象出一个基本产品,然后各产品在具体实现上各显神通。工厂则依据业务需求的复杂程度,如果业务简单层次不多,那么一个工厂类就够用了,此时叫做工厂方法模式;如果业务复杂层次较多,那么连工厂也要进行抽象化,先抽象出基本工厂,然后派生出具体的工厂,最后具体的工厂再去制造产品,此时叫做抽象工厂模式。
Android中的使用场合
工厂模式在概念上相当规范,但实际开发中往往有所取舍,并不完全遵循工厂模式的定义规范。Android源码中类似工厂模式的地方主要有三处,分别是值工厂、实例工厂、类工厂。值工厂
值工厂的输入参数是基本数据类型,根据不同的数值进行分支处理。值工厂的代表源码是Activity类的getSystemService方法,该方法根据输入的服务名称字符串,返回对应的服务管理类的对象。有关getSystemService支持的系统服务管理类清单可见《Android开发笔记(六十一)文件下载与上传》。下面是getSystemService方法的源码:
@Override public Object getSystemService(String name) { if (getBaseContext() == null) { throw new IllegalStateException( "System services not available to Activities before onCreate()"); } if (WINDOW_SERVICE.equals(name)) { return mWindowManager; } else if (SEARCH_SERVICE.equals(name)) { ensureSearchManager(); return mSearchManager; } return super.getSystemService(name); }
实例工厂
实例工厂的输入参数是类的实例,不过这个实例可能是由不同派生类的对象,所以工厂内部得使用instanceof判断该实例属于哪个派生类,然后再做相应处理。实例工厂的代表源码是BitmapFactory的decodeStream方法,该方法中判断如果输入流是AssetInputStream的实例,那么调用jni接口nativeDecodeAsset,否则最终调用jni接口nativeDecodeStream。从这个代码可以看出,android对asset路径下的图片与磁盘路径下的图片操作是不一样的,只是工厂模式为我们屏蔽了它们之间的区别,有关asset目录下读取图片文件的操作参见《Android开发笔记(二十五)assets目录的文件读取》。下面是decodeStream方法的源码:
public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) { // we don't throw in this case, thus allowing the caller to only check // the cache, and not force the image to be decoded. if (is == null) { return null; } Bitmap bm = null; Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeBitmap"); try { if (is instanceof AssetManager.AssetInputStream) { final int asset = ((AssetManager.AssetInputStream) is).getAssetInt(); bm = nativeDecodeAsset(asset, outPadding, opts); } else { bm = decodeStreamInternal(is, outPadding, opts); } if (bm == null && opts != null && opts.inBitmap != null) { throw new IllegalArgumentException("Problem decoding into existing bitmap"); } setDensityFromOptions(bm, opts); } finally { Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS); } return bm; }
类工厂
类工厂的输入参数为类名,这得用模板来表示了。类工厂用的就比较多,比如java的容器类ArrayList、HashMap等等都用到了类工厂,有关容器类的说明参见《Android开发笔记(二十六)Java的容器类》。当然了,容器类是java自带的,若要问Android的类工厂,那得数AsyncTask,有关AsyncTask的说明参见《Android开发笔记(四十九)异步任务处理AsyncTask》。话说AsyncTask的模板一口气用到了三个类参数,而且许多成员方法都用到了类参数,因此开发中还没法直接使用AsyncTask,得重新编写它的派生类,并重写相关方法。下面是AsyncTask的源码节选:
public abstract class AsyncTask<Params, Progress, Result> { private final WorkerRunnable<Params, Result> mWorker; private final FutureTask<Result> mFuture; protected abstract Result doInBackground(Params... params); protected void onPreExecute() { } protected void onPostExecute(Result result) { } protected void onProgressUpdate(Progress... values) { } protected void onCancelled(Result result) { onCancelled(); } public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); } public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) { if (mStatus != Status.PENDING) { switch (mStatus) { case RUNNING: throw new IllegalStateException("Cannot execute task:" + " the task is already running."); case FINISHED: throw new IllegalStateException("Cannot execute task:" + " the task has already been executed " + "(a task can be executed only once)"); } } mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params; exec.execute(mFuture); return this; } }
点此查看Android开发笔记的完整目录
相关文章推荐
- 六款值得推荐的android(安卓)开源框架简介
- android Launcher 替换
- Android_实用技术(3)—— Service简析(Ⅱ)
- Android Studio 出错点
- Android全局异常捕获
- Android 开发之RecyclerView 实现ListView (一)
- android——实现点击两次返回按钮退出程序
- Android 中的onKeyDown
- RecyclerView 的使用
- android support v4,v7,v13兼容包及其它依赖包
- Android APK 中启动特定的 bin 服务
- Android基础--高德地图定位简单介绍
- android通话时第二通电话呼叫等待提示音音量大小
- Android学习(36) -- 自定义控件(1)实现组合按钮的菜单和隐藏
- Android 使用ViewDragHelper实现向slidingMenu侧滑菜单的效果
- Android---open failed: ENOENT (No such file or directory) 错误
- 仿电商(京东等)的列表分类展示案例
- Android中fragment注意事项
- Android安全机制分析
- android 安全机制