单例的使用场景很多,如可以通过单例实现应用缓存,这样多个线程统一对一块内存进行读写数据,既保障了数据的唯一性,又提高了业务处理性能。又比如使用单例实现应用的全局配置管理,保障全局有且仅有一个配置管理对象。
单例模式简介
单例是设计模式使用最为普遍的模式之一。它是一种对象创建模式,用于产生一个对象的具体实例,它可以确保系统中(单进程),一个类只产生一个实例。它的优势在于:
- 对于频繁使用的对象,可以省略new操作花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销;
- 由于new操作的次数减少,因此对系统内存的使用频率也会降低,这样将减少GC压力。
严格来说单例模式与并行没有直接的关系,是因为它太常见了,在应用开发的过程中将不可避免的会在多线程环境中使用到它。
创建一个单例类
由于单例类需要在多个模块间使用,因此单例类的本质是一个Sendable共享对象,创建一个单例类型最常用的有饿汉式和懒汉式,除此之外还有双重检查模式(这个不在本文中介绍)
注意:单例类需要使用[“use shared”]指令来标记,"use shared"需写在import语句之后,其他语句之前。
饿汉式
饿汉式:此种方式在类加载时,静态实例instance就已经创建并初始化好了。(这种方式当前有BUG,待BUG修复后删除此说明)
"use shared"
@Sendable
export class SingletonClassE {
static instance: SingletonClassE = new SingletonClassE();
private constructor() {
}
public doSomething() {
}
}
//使用方式
function doSomething() {
SingletonClassE.instance.doSomething()
}
此处没有将instance申明为private类型并提供getInstance静态方法,得益于ArkTS的语法校验,外界无法通过SingletonClass.instance = null/undefined/new SingletonClass()的方式给instance实例赋值。
根据使用习惯,也可以将instance申明为private类型,并提供静态方法getInstance()获取instance实例。
"use shared"
@Sendable
export class SingletonClassE {
private static instance : SingletonClassE = new SingletonClassE();
private constructor() {
}
public static getInstance() : SingletonClassE {
if (!SingletonClassE.instance) {
SingletonClassE.instance = new SingletonClassE();
}
return SingletonClassE.instance;
}
public doSomething() {
}
}
//使用方式
function doSomething() {
SingletonClassE.getInstance().doSomething()
}
</