设计模式--单例模式
单例模式
一个类只能产生一个对象。确保某一个只有一个实例,而且自行实例化并向整个系统提供这个实例且构造函数私有化。
1 |
|
单例模式优点
- 由于单例模式只存在一个实例,减少了内存开支
- 减少了系统的开销
- 避免对资源的多重占用
- 在系统设置全局访问点,优化和共享资源访问
- 允许可变数目的实例,基于单例模式可以进行拓展,可以获得指定个数的对象实例,既节省系统资源,又解决单例对象过多的性能损耗
单例模式缺点
- 单例模式一般没有接口,扩展很困难。
- 单例模式对测试是不利的,因为单例模式没有完成时,是不能进行测试的。
- 与单一职责原则有冲突
单例模式使用场景
- 要求生成唯一序列号的环境
- 在整个项目中需要一个共享访问点或共享数据
- 创建一个对象需要的消耗资源过多,如访问IO和数据库
- 需要定义大量的静态常亮和静态方法
单例模式的实现条件
构造函数私有
有一个该类的静态私有对象
有一个静态的公用函数用于创建或获取本身静态私有对象
- 线程同步
单例模式注意事项
- 在高并发情况下,注意单例模式的线程同步问题
- 考虑对象的复制情况
单例模式实现实例
双重校验锁(DCL)–Java5之后可以安心使用该方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public class Singleton {
private static volatile Singleton mInstance;
private Singleton() {
}
public static Singleton getInstance() {
if (mInstance == null) {
synchronized (Singleton.class) {
if (mInstance == null) {
mInstance = new Singleton();
}
}
}
return mInstance;
}
//反序列化提供的一个特殊方法,可以控制对象的反序列化
private Object readResolve(){
return mInstance;//返回实例对象
}
}在JVM中,并不限制处理器的执行顺序,在不影响运行结果的情况下,顺序可能会被打乱。volatile 关键字的作用是防止执行命令不会被重新排序。如若没有volatile 修饰,则
mInstance = new Singleton();
可能出现mInstance
尚未被初始化的异常。mInstance = new Singleton();
包括三步:为对象分配内存
,执行构造方法,初始化实例对象
,把mInstance的引用指向分配的内存空间
。在JVM的执行过程中并不是原子性的。静态内部类
1
2
3
4
5
6
7
8
9
10
11public class Singleton{
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
private Singleton(){
}
public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
}为何可以保证线程安全?
虚拟机可以保证一个类的类构造器
()`在多线程环境中被正确的加锁、同步。如果多个线程同时去初始化一个类,只有一个线程可以去执行类构造方法,其他线程都会阻塞等待,直到构造方法执行完毕。同一个类加载器下,一个类型只会被初始化一次。 枚举
1
2
3public enum Singleton {
INSTANCE;
}防止反序列化重新创建新对象,在Android中不建议使用枚举,大概会增加4倍消耗。
单例模式在Android中的体现
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!