定义
- 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例
优缺点
-
优点
-
在整个内存中只有一个实例,减少了内存开支。
-
由于单例模式只生成一个实例, 所以可减少系统的性能开销
-
可以避免对资源的多重占用
-
可在系统设置全局的访问点,优化和共享资源访问
-
-
缺点
-
单例模式一般没有接口,扩展很困难,若要修改,除了修改代码基本没有第二种途径可以实现
-
不利于单元测试
-
单例类职责过重,在一定程度上,违背了单一职责
-
使用场景
-
在整个项目中需要一个共享访问点或共享数据。
-
创建一个对象时消耗的资源过多时,但又经常用到的对象
-
频繁访问数据库或文件的对象
实现方式
-
单例之懒汉式
-
第一次调用才初始化,在效率上会有一点延迟,但可避免内存浪费
-
非线程安全,用于多线程会出现问题
-
-
单例之饿汉式
-
在类加载时就初始化了,若实例没有使用时,将会造成内存浪费
-
线程安全,可直接用于多线程而不出现问题
-
代码实现
-
懒汉式之一般方式
适用于单线程模式,延迟加载
-
Java版本
public class LazySingleTon { private static LazySingleTon instance; private LazySingleTon(){ } public static LazySingleTon getInstance() { if(instance==null){ instance=new LazySingleTon() } return instance; }
}
-
Kotlin版本
class LazySingleTon private constructor(){ companion object { private val instance:LazySingleTon?=null get(){ if(field==null){ field= LazySingleTon() } return field } } }
-
-
懒汉式之双重校验方式
使用synchronized添加同步锁,这样就可以使在初始化时在同一时间内只有一个线程可以对其访问,解决多线程同时访问的问题;但是也可能偶尔失效
-
Java版本
public class LazySingleTon { private static LazySingleTon instace; private LazySingleTon() { } public static LazySingleTon newStance() {instace if(instace==null){ synchronized (LazySingleTon.class){ if(instace==null){ instace=new LazySingleTon(); } } } return instace; } public void test() { } }
-
Kotlin版本
class LazySingleTon { companion object { val instance:LazySingleTon by lazy(mode =LazyThreadSafetyMode.SYNCHRONIZED) { LazySingleTon() } } }
-
-
懒汉式之静态内部类
使用静态内部类,只有当第一次调用newStance()时,虚拟机才会加载LazySingleTonHolder静态内部类,能够保证线程安全以及实例的唯一性
-
Java版本
public class LazySingleTon { private LazySingleTon() { } private static class LazySingleTonHolder { private static LazySingleTon INSTANCE = new LazySingleTon(); } public static LazySingleTon newStance() { return LazySingleTonHolder.INSTANCE; } public void test() { } }
-
Kotlin版本
class LazySingleTon { companion object { val instance:LazySingleTon =LazySingletonHolder.holder } } private object LazySingletonHolder{ val holder:LazySingleTon=LazySingleTon() } }
-
-
饿汉式
类加载就会创建实例而不去管你用不用, 但是内存使用率低 线程安全。因为虚拟机保证了类只会加载一次,在装载类的时候是不会并发的
-
Java版本
public class HungrySingleton { private static HungrySingleton INSTANCE = new HungrySingleton(); private HungrySingleton() { } public static HungrySingleton newStance() { return INSTANCE; } public void test() { } }
-
Kotlin版本
object HungrySingleton { fun test() { } }
-
单例模式扩展之多例模式
-
作用
在设计时决定在内存中有多少个实例,方便系统进行扩展,修正单例可能存在的性能问题,提升系统的响应速度
-
代码实现
-
创建有上线的多例模式
import android.util.Log; import java.util.Random; import java.util.Vector; public class MultipleObjectsSington { /**限制对象最多的个数*/ private static int maxObjectNum=2; /**当前对象的索引值*/ private static int mCurrentObjectNum=0; /**用于存储多个对象*/ private static Vector<MultipleObjectsSington> objects=new Vector<>(); private static Vector<String> names=new Vector<>(); static { objects.add(new MultipleObjectsSington("1")); objects.add(new MultipleObjectsSington("2")); } private MultipleObjectsSington(){ this(""); } private MultipleObjectsSington(String name ){ names.add(name); } /** * 获取对象实例 * @return */ public static MultipleObjectsSington getInstance(){ Random random=new Random(); mCurrentObjectNum=random.nextInt(maxObjectNum); return objects.get(mCurrentObjectNum); } /** * 对外暴露的方法 */ public void say(){ Log.i("MultipleObjectsSington","这是第几个对象:"+names.get(mCurrentObjectNum)); } }
-
客户端调用
for (i in 0 until 5) { val instance= MultipleObjectsSington.getInstance() instance.say() }
-
结果
这是第几个对象:1 这是第几个对象:1 这是第几个对象:2 这是第几个对象:2 这是第几个对象:2
-