首页 > 编程语言 >【设计模式】工厂方法模式——工厂方法模式在Android SDK源码中的应用

【设计模式】工厂方法模式——工厂方法模式在Android SDK源码中的应用

时间:2024-01-13 10:35:38浏览次数:28  
标签:return NonNull cl create 工厂 源码 modelClass 设计模式 public

工厂方法模式在Android SDK源码中有广泛的应用,无论app层还是framework层,无论是Java实现的还是Kotlin实现的。


BitmapFactory

Bitmap的构造方法都没有被public修饰,开发者必须用BitmapFactory来生成Bitmap对象,BitmapFactory中用于生产Bitmap实例的工厂方法如下:

public class BitmapFactory {
    
    // ……代码省略……
    
    /**
     * Decode a file path into a bitmap. If the specified file name is null,
     * or cannot be decoded into a bitmap, the function returns null.
     */
    public static Bitmap decodeFile(String pathName, Options opts) {
        // ……代码省略……       
        return bm;
    }

    /**
     * Synonym for opening the given resource and calling
     */
    public static Bitmap decodeResource(Resources res, int id, Options opts) {
        // ……代码省略……
        return bm;
    }

    /**
     * Decode an immutable bitmap from the specified byte array.
     */
    public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) {
        // ……代码省略……
        return bm;
    }

    /**
     * Decode an input stream into a bitmap. If the input stream is null, or
     * cannot be used to decode a bitmap, the function returns null.
     * The stream's position will be where ever it was after the encoded data
     * was read.
     */
    @Nullable
    public static Bitmap decodeStream(@Nullable InputStream is, @Nullable Rect outPadding,
            @Nullable Options opts) {
        // ……代码省略……
        return bm;
    }

    /**
     * Decode a bitmap from the file descriptor. If the bitmap cannot be decoded
     * return null. The position within the descriptor will not be changed when
     * this returns, so the descriptor can be used again as-is.
     */
    public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) {
        // ……代码省略……
        return bm;
    }

    // ……代码省略……
    
}

可见BitmapFactory生产Bitmap对象的方法都是用static修饰的静态方法,是典型的简单工厂。


AppComponentFactory

众所周知Application和四大组件都是不能直接new出来的,需要通知system-server之后才能在当前进程生成实例。AppComponentFactory用来生产Applicaiton和四大组件的工厂方法代码如下:

public class AppComponentFactory {

    public @NonNull ClassLoader instantiateClassLoader(@NonNull ClassLoader cl,
            @NonNull ApplicationInfo aInfo) {
        return cl;
    }

    public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
            @NonNull String className)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Application) cl.loadClass(className).newInstance();
    }

    public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
            @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Activity) cl.loadClass(className).newInstance();
    }

    public @NonNull BroadcastReceiver instantiateReceiver(@NonNull ClassLoader cl,
            @NonNull String className, @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (BroadcastReceiver) cl.loadClass(className).newInstance();
    }

    public @NonNull Service instantiateService(@NonNull ClassLoader cl,
            @NonNull String className, @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Service) cl.loadClass(className).newInstance();
    }

    public @NonNull ContentProvider instantiateProvider(@NonNull ClassLoader cl,
            @NonNull String className)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (ContentProvider) cl.loadClass(className).newInstance();
    }

    /**
     * @hide
     */
    public static final AppComponentFactory DEFAULT = new AppComponentFactory();
}

生成Application和四大组件实例都是靠工厂方法生成,注意最后一行的单例模式的懒汉式实现,AppComponentFactory同时利用了工厂方法模式和单例模式。

在Android源码中简单工厂的应用非常广泛,是否有多工厂的应用呢?答案是有的,就是Jetpack组件里的ViewModelProvider.Factory。


ViewModelProvider.Factory

众所周知ViewModel作为MVVM架构中的VM,是不能直接new出来的,必须是用ViewModelProvider生成,我们来看源码:

@MainThread
public open operator fun <T : ViewModel> get(modelClass: Class<T>): T {
    val canonicalName = modelClass.canonicalName
        ?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels")
    return get("$DEFAULT_KEY:$canonicalName", modelClass)
}

@MainThread
public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
	val viewModel = store[key]
    if (modelClass.isInstance(viewModel)) {
        (factory as? OnRequeryFactory)?.onRequery(viewModel!!)
        return viewModel as T
    } else {
        @Suppress("ControlFlowWithEmptyBody")
        if (viewModel != null) {
            // TODO: log a warning.
        }
    }
    val extras = MutableCreationExtras(defaultCreationExtras)
    extras[VIEW_MODEL_KEY] = key
    // AGP has some desugaring issues associated with compileOnly dependencies so we need to
    // fall back to the other create method to keep from crashing.
    return try {
        factory.create(modelClass, extras)
    } catch (e: AbstractMethodError) {
        factory.create(modelClass)
    }.also { store.put(key, it) }
}

// 用接口实现的抽象工厂
public interface Factory {
	public fun <T : ViewModel> create(modelClass: Class<T>): T {
    	throw UnsupportedOperationException(
            "Factory.create(String) is unsupported.  This Factory requires " +
                    "`CreationExtras` to be passed into `create` method."
        )
    }
    
    // ……代码省略……
}

// 具体工厂之一
@Suppress("SingletonConstructor")
public open class NewInstanceFactory : Factory {
	@Suppress("DocumentExceptions")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        return try {
            modelClass.getDeclaredConstructor().newInstance()
        } catch (e: NoSuchMethodException) {
            throw RuntimeException("Cannot create an instance of $modelClass", e)
        } catch (e: InstantiationException) {
            throw RuntimeException("Cannot create an instance of $modelClass", e)
        } catch (e: IllegalAccessException) {
            throw RuntimeException("Cannot create an instance of $modelClass", e)
        }
    }
    // ……代码省略……
}

// 具体工厂之二
public open class AndroidViewModelFactory
    private constructor(
        private val application: Application?,
        // parameter to avoid clash between constructors with nullable and non-nullable
        // Application
        @Suppress("UNUSED_PARAMETER") unused: Int,
    ) : NewInstanceFactory() {

	/**
	 * Constructs this factory.
     */
    @Suppress("SingletonConstructor")
    public constructor() : this(null, 0)

	@Suppress("SingletonConstructor")
    public constructor(application: Application) : this(application, 0)

    @Suppress("DocumentExceptions")
    override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T {
		return if (application != null) {
            create(modelClass)
        } else {
            val application = extras[APPLICATION_KEY]
            if (application != null) {
                create(modelClass, application)
            } else {
                // For AndroidViewModels, CreationExtras must have an application set
            if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) {
                throw IllegalArgumentException(
                    "CreationExtras must have an application by `APPLICATION_KEY`"
                )
            }
            super.create(modelClass)
            }
        }
    }

    @Suppress("DocumentExceptions")
   	override fun <T : ViewModel> create(modelClass: Class<T>): T {
		return if (application == null) {
			throw UnsupportedOperationException(
            	"AndroidViewModelFactory constructed " +
					"with empty constructor works only with " +
                    "create(modelClass: Class<T>, extras: CreationExtras)."
            )
        } else {
            create(modelClass, application)
        }
    }
    
    // ……代码省略……
}

不直接new出ViewModel对象而用工厂方法生成的原因是如果ViewModelStore中存在对象,则返回该对象,不存在才new出新对象。除了ViewModelProvider.AndroidViewModelFactory之外,接口ViewModelProvider.Factory还有许多实现的子类,而且AndroidViewModelFactory也是用open修饰的,也是为了让其他类继承的,这是典型的工厂模式的多工厂。



标签:return,NonNull,cl,create,工厂,源码,modelClass,设计模式,public
From: https://blog.51cto.com/dongfeng9ge/9229763

相关文章

  • Springcloud智慧工地管理云平台源码 AI智能识别
    智慧工地解决方案一、现状描述 建筑工程建设具有明显的生产规模大宗性与生产场所固定性的特点。建筑企业70%左右的工作都发生在施工现场,施工阶段的现场管理对工程成本、进度、质量及安全等至关重要。同时随着工程建设规模不断扩大,工艺流程纷繁复杂,如何搞好现场施工现场管理,控制......
  • 新一代工厂融合广播系统,助力工业行业可持续发展
     在当今高度竞争的工业环境中,工厂的运营效率和生产安全至关重要。为了实现这一目标,新一代工厂融合广播系统应运而生,将指挥中心、值班中心、融合通信调度主机、厂区终端和防爆话机紧密连接,构建了一个全面、高效的通信网络。系统拓扑图 指挥中心与值班中心的高效协同指挥中......
  • 迅为RK3568开发板编译Android12源码包-修改编译线程数
    在编译 Android 系统时,可以通过调整线程数来控制并行编译的任务数量,使用多线程可以加快构建速度。要注意根据 Ubuntu 的处理器内核总数以及内存大小来设置合适的线程数。过高的线程数可能导致系统资源的竞争,过低的线程数则不能充分利用系统的并行处理能力。找到合适的线程数可......
  • Java医院智慧3D导诊系统源码 小程序源码
    医院智慧3D导诊系统,通过输入疾病症状和选择部位进行导诊挂号,支持小程序端、APP端开发背景人们经常去医院因为不知道挂什么科而烦恼,有些病人不方便问又不好意思问。在互联网医院中挂号且又不知该挂什么科,找什么类型的医生,这些不足,给患者带来了极大的不便,甚至可能严重耽误病情。1......
  • springboot医院信息化云HIS运维平台源码 SaaS模式
    一、HIS系统HIS系统是医院最主要的系统,它主要涵盖基本流程功能,是医院系统的核心业务系统。这里的HIS指的是狭义的HIS系统,仅仅包括门诊、住院的医嘱结算相关功能的系统。一般门诊和住院是同一个系统,包括以下一些工作站:1、门诊部分挂号及预约、划价及收费、门诊处方及病历、医生排......
  • 智能导诊AI引擎,智慧医院智能导诊系统源码,以智能问答的人机对话形式精准推荐科室
    什么是智能导诊?智能导诊系统是在医liao中使用的引导患者自助就诊挂号,在就诊的过程中有许多患者不知道需要挂什么号,要看什么病,通过智慧导诊系统,可输入自身疾病的症状表现,或选择身体部位,在经由智慧导诊系统多维度计算,准确推荐科室,引导患者挂号就诊,实现科学就诊,不用担心挂错号。在日常......
  • 【设计模式】工厂方法模式——工厂方法模式在JDK源码中的应用
    工厂方法模式在JDK源码中有很多应用场景,不仅有简单工厂模式,还有多工厂模式。Executors尽管ThreadPoolExecutor及其子类都是可以直接new出来的,但Executors还是提供了生产常用ThreadPoolExecutor实例的简单工厂:publicclassExecutors{/***Createsathreadpoolthat......
  • PHP+uniapp进销存源码|erp源码计算机毕业设计[附源码]
     企业资源规划(ERP)是一种软件系统,可帮助组织自动化和管理核心业务流程以获得最佳性能。ERP软件协调公司业务流程之间的数据流,提供单一事实来源并简化整个企业的运营。它能够将公司的财务、供应链、运营、商业、报告、制造和人力资源活动连接到一个平台上。 大多数公司都......
  • [转帖]从Linux源码看TIME_WAIT状态的持续时间
    https://zhuanlan.zhihu.com/p/286537295 从Linux源码看TIME_WAIT状态的持续时间前言笔者一直以为在Linux下TIME_WAIT状态的Socket持续状态是60s左右。线上实际却存在TIME_WAIT超过100s的Socket。由于这牵涉到最近出现的一个复杂Bug的分析。所以,笔者就去Linux源码里面,......
  • Python实现软件设计模式8:桥接模式 Bridge Pattern
    动机将抽象部分与实现部分分离,使他们都可以独立地变化。用抽象关联取代传统的多层继承。将类之间的静态继承关系转换为动态的对象组合关系。上图展示的软件系统中存在两个独立地变化维度,分别是抽象类(Abstraction)和实现类(Implementor),它俩都是接口、都分别可以独立地扩展出多......