一、定义
确保一个类只有一个实例,并向整个系统提供这个实例。
二、产生条件
1.构造方法私有化
2.提供一个共有的静态方法,返回该类的一个实例
三、优缺点
优点:
1.减少内存开支,避免反复创建和销毁。
2.只有一个实例,减少系统性能开销,特别是产生一个对象需要比较多的资源时。
3.避免对资源的多重占用,例如写文件动作,只有一个实例存在可以避免对同一个资源文件的同时写操作。
4.单例模式可以在系统设置全局的访问点,优化和共享资源访问。
缺点:
1.单例模式一般无接口,扩展困难。
2.对测试不利,单例类未完成时不能进行测试。
3.与单一职责原则有冲突,单例模式把要单例的业务逻辑融合在一个类中。
四、写法解析
1.懒汉式
class Single {
private static Single single = null;
private Single() {
}
public static Single getInstance() {
if (single == null)
single = new Single();
return single;
}
}
实现了懒加载(使用时才创建),但多线程下可能会创建多个实例,高并发场景下不建议使用这个形式,可以添加 synchronized 关键字,例如
class Single {
private static volatile Single single = null;
private Single() {
}
public static Single getInstance() {
if (single == null) {
synchronized (Single.class) {
if (single == null)
single = new Single();
}
}
return single;
}
}
synchronized 关键字之所以不加在方法上是因为加锁是比较费时的,当访问频繁时可能会拖慢速度,因此放在方法内进行双重判断(双重校验锁)是比较好的做法。volatile 关键字保证了 single 单例的原子性。
2.饿汉式
class Single {
private static Single single = new Single();
private Single() {
}
public static Single getInstance() {
return single;
}
}
完美的解决了高并发场景下可能创建多个实例的问题,不过在类加载时就会进行创建实例,可能你暂时用不到这个实例而造成多余的开销,特别是实例化这个对象需要较多的资源时。
如果这个实例是确定一定会使用到的,建议可以选择使用饿汉式
3.静态内部类
public class Singleton {
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return LazyHolder.INSTANCE;
}
}
既解决了高并发时可能创建多个实例的问题,又避免了饿汉式在类加载时就进行创建实例的问题,实现懒加载。
查看更多:设计模式分类以及六大原则