基本概念

工厂模式是一种常用的实例化对象设计模式。

程序开发很多时候都在不停地敲if、else,因为业务需求总在发展变化,今天客户要求生产A产品,明天客户要求把A产品稍微改改变成B产品,当然A产品与B产品的基本特性差不多,只在某些细节上存在差异。可是这样推陈出新就害苦了程序员,每次变动都得加上一堆的if、else,而且随着产品数量变多,程序代码也越来越难以维护。

工厂模式的出现便是要解决这种困惑,它把产品制造分为两种参与对象,第一种是制造出来的产品,第二种是负责制造的工厂。各产品肯定要进行抽象出一个基本产品,然后各产品在具体实现上各显神通。工厂则依据业务需求的复杂程度,如果业务简单层次不多,那么一个工厂类就够用了,此时叫做工厂方法模式;如果业务复杂层次较多,那么连工厂也要进行抽象化,先抽象出基本工厂,然后派生出具体的工厂,最后具体的工厂再去制造产品,此时叫做抽象工厂模式。

Android中的使用场合

工厂模式在概念上相当规范,但实际开发中往往有所取舍,并不完全遵循工厂模式的定义规范。Android源码中类似工厂模式的地方主要有三处,分别是值工厂、实例工厂、类工厂。

值工厂

值工厂的输入参数是基本数据类型,根据不同的数值进行分支处理。值工厂的代表源码是Activity类的getSystemService方法,该方法根据输入的服务名称字符串,返回对应的服务管理类的对象。有关getSystemService支持的系统服务管理类清单可见《 Android开发笔记(六十一)文件下载管理DownloadManager》。

下面是getSystemService方法的源码:

    @Overridepublic 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开发笔记(九十一)工厂模式相关推荐

  1. Android开发笔记(九十)建造者模式

    基本概念 建造者模式是一种常用的设计模式,它用于把类的表现和构建分离开来.引入建造者模式的缘由,且看博主下面细细道来. 公开属性 一般我们定义一个类的属性,如果属性是公开的,那可以直接对该类的属性赋值 ...

  2. Android开发笔记(一百六十七)Android8.0的画中画模式

    前面的博文< Android开发笔记(一百五十九)Android7.0的分屏模式>介绍了Android7.0的多窗口特性,但是这个分屏的区域是固定的,要么在屏幕的上半部分,要么在屏幕的下半 ...

  3. Android开发笔记(一百六十)休眠模式下的定时器控制

    定时器AlarmManager常常用于需要周期性处理的场合,比如闹钟提醒.任务轮询等等.并且定时器来源于系统服务,即使App已经不在运行了,也能收到定时器发出的广播而被唤醒.似此回光返照的神技,便遭到 ...

  4. Android开发笔记(一百五十九)Android7.0的分屏模式

    现在的手机屏幕越来越大,使得在屏幕上同时开多个窗口不再奢侈,因此Android从7.0开始顺势推出了分屏功能,也被称作多窗口模式.比如把竖长的手机屏幕分成上下两个窗口,一边在上面的窗口中观看电影,一边 ...

  5. Android开发笔记(九十八)往图片添加部件

    添加圆角 添加圆角的功能,要用到Canvas类的drawRoundRect方法,即把画布裁剪成指定的圆角矩形. 下面是给图片添加圆角的效果截图: 下面是给图片添加圆角的代码片段: public sta ...

  6. Android开发笔记(九十六)集合动画与属性动画

    集合动画AnimationSet 补间动画有四大类:透明度动画AlphaAnimation.旋转动画RotateAnimation.缩放动画ScaleAnimation.平移动画TranslateAn ...

  7. Android开发笔记(九十五)自定义Drawable

    Drawable Bitmap是Android对图像的定义描述,而Drawable则是对图像的展现描述,在View视图中显示图像都是通过Drawable来实现的.其中有关Bitmap的介绍参见< ...

  8. Android开发笔记(九十四)图片的基本加工

    位图管理Bitmap Android上的图形使用Drawable类,而位图管理则使用Bitmap类,java上与之对应的是awt包中的BufferedImage.Android开发中有需要对jpg.p ...

  9. Android开发笔记(九十三)装饰模式

    基本概念 装饰模式是扩展功能用的一种设计模式, 一般要扩展功能,我们都会想到继承,可是继承只能继承一个基类,如果有多个条件需要分别进行扩展,那得写好几个派生类,条件越多派生类的数量也越多. 上面描述比 ...

最新文章

  1. MySQL从入门到搞定实战
  2. 深入理解软件和硬件(国庆精彩活动预告)
  3. 简介DOTNET 编译原理 简介DOTNET 编译原理 简介DOTNET 编译原理
  4. C#枚举类型的常用操作总结
  5. jstat命令(Java Virtual Machine Statistics Monitoring Tool
  6. JAVA仿真之银行出纳员
  7. vs2010 打开项目卡死问题解决办法
  8. 计算机视觉图像去噪原理,AI笔记: 计算机视觉之图像滤波去噪: 原理、方法和效果比较...
  9. linux 下安装wps
  10. Sublime Text 2 注册码/破解方法【蕃薯耀】
  11. 矩阵的逆矩阵 和 转置矩阵
  12. 程序员真的很孤独吗?
  13. 开发了一款开虚拟店通过百度网盘卖成千上万本电子书虚拟商品自动发货机器人软件助手
  14. 从点阵到OLED屏幕——动态扫描显示原理
  15. play框架使用起来(17)
  16. Linux笔记1(安装,目录结构,远程登录,vi和vim,用户管理,实用指令。定时调度,挂载。)
  17. 计算机基础是不是java_计算机基础与java
  18. Java程序员11面阿里,错失offer,期间还面了EMC+网易+美团......
  19. RecyclerView+网络加载数据图片+属性动画对角平移透明
  20. 高手分享:善用组策略禁止不明U盘使用_xitongshoucang.com

热门文章

  1. Leetcode每日一题:面试题17.10.find-majority-element-lcci(主要元素)
  2. POJ1321(深搜)
  3. 有高手想换工作的么?
  4. 自动化测试学习之路--HTML常见元素、属性的简单学习
  5. 若依同时集成jsp和thymeleaf解决方案
  6. linux编译时开启宏,【spec】Linux上编译安装的spec文件中的常用路径以及宏变量
  7. php和js搜索框,利用PHP+JS实现搜索自动提示(实例)_php技巧
  8. Spring Boot快速搭建Web开发框架(Hibernate+Thymeleaf)
  9. java 获取系统变量(环境变量和设置变量)
  10. Visual Studio 编写纯C语言程序