单例模式
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。构造器私有化,不能被new出来。
项目代码:Github
单例的应用
优点
- 在内存中只有一个实例, 减少了内存开支
- 当一个对象的产生需要 比较多的资源时, 如读取配置、 产生其他依赖对象时, 则可以通过在应用启动时直接产生一 个单例对象, 然后用永久驻留内存的方式来解决
- 单例模式可以避免对资源的多重占用, 例如一个写文件动作, 由于只有一个实例存在 内存中, 避免对同一个资源文件的同时写操作。
- 单例模式可以避免对资源的多重占用, 例如一个写文件动作, 由于只有一个实例存在 内存中, 避免对同一个资源文件的同时写操作。
缺点
- 单例模式一般没有接口, 扩展很困难;
- 单例模式对测试是不利的。 在并行开发环境中, 如果单例模式没有完成, 是不能进行 测试的, 没有接口也不能使用mock的方式虚拟一个对象。
- 单例模式与单一职责原则有冲突。
几种单例实现:
1、饿汉模式
1 | public class SingleDemo { |
优点:
- 实例的初始化由JVM装载类的时候进行,保证了线程的安全性
- 实现简单方便,访问效率高
缺点:
- 不能实现懒加载,资源的利用率不高
2、懒汉模式
1 | public class SingleDemo2 { |
优点:
- 只有使用这个类的时候才初始化实例,优化了资源利用率
缺点:
- 为了实现线程安全,使用了同步方法获取,增加了访问的开销
3、双重检查
1 | public class SingleDemo3 { |
优点:
- 实现懒加载
- 通过缩小同步区域和第一次检查提高访问效率
缺点:
- 为了实现线程安全,使用了同步方法获取,增加了访问的开销
4、静态内部类
1 | public class SingleDemo4 { |
优点:
- 即实现了线程安全,又实现了懒加载
缺点:
- 实现稍显复杂
5、枚举类
1 | public enum SingleDemo5 { |
优点:
- 实现简单
- 线程安全
缺点:
- 不能实现懒加载
结论
如果需要懒加载就使用静态内部类方式,如果不需要就使用枚举方式
单例模式的扩展
如果要求一个类只能生产固定数量的实例。
1 | public class SingleDemo6{ |
这种需要产生固定数量对象的模式就叫做有上限的多例模式, 它是单例模式的一种扩展, 采用有上限的多例模式, 我们可以在设计时决定在内存中有多少个实例, 方便系统进行 扩展, 修正单例可能存在的性能问题, 提供系统的响应速度。 例如读取文件, 我们可以在系 统启动时完成初始化工作, 在内存中启动固定数量的reader实例, 然后在需要读取文件时就 可以快速响应。