前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(九十一)工厂模式

Android开发笔记(九十一)工厂模式

作者头像
aqi00
发布2019-01-18 14:05:50
5090
发布2019-01-18 14:05:50
举报
文章被收录于专栏:老欧说安卓老欧说安卓

基本概念

工厂模式是一种常用的实例化对象设计模式。 程序开发很多时候都在不停地敲if、else,因为业务需求总在发展变化,今天客户要求生产A产品,明天客户要求把A产品稍微改改变成B产品,当然A产品与B产品的基本特性差不多,只在某些细节上存在差异。可是这样推陈出新就害苦了程序员,每次变动都得加上一堆的if、else,而且随着产品数量变多,程序代码也越来越难以维护。 工厂模式的出现便是要解决这种困惑,它把产品制造分为两种参与对象,第一种是制造出来的产品,第二种是负责制造的工厂。各产品肯定要进行抽象出一个基本产品,然后各产品在具体实现上各显神通。工厂则依据业务需求的复杂程度,如果业务简单层次不多,那么一个工厂类就够用了,此时叫做工厂方法模式;如果业务复杂层次较多,那么连工厂也要进行抽象化,先抽象出基本工厂,然后派生出具体的工厂,最后具体的工厂再去制造产品,此时叫做抽象工厂模式。

Android中的使用场合

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

值工厂

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

代码语言:javascript
复制
    @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方法的源码:

代码语言:javascript
复制
    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的源码节选:

代码语言:javascript
复制
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开发笔记的完整目录

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年04月22日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基本概念
  • Android中的使用场合
    • 值工厂
      • 实例工厂
        • 类工厂
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档