谈谈单例模式
单例模式的几种实现
饿汉式:
在类加载时就初始化创建对象,是线程安全的,不管何时使用都会创建,可能会浪费内存,所以称之为饿汉。
public class HungrySingleton {
private static HungrySingleton instance = new HungrySingleton();
private HungrySingleton(){}
public static HungrySingleton getInstance(){
return instance;
}
}
懒汉式:
在被外部调用时才会加载创建,是线程不安全的,加锁保证线程安全但效率变低。通俗的来讲,别人叫它去干活它才去,所以称之为懒汉。
public class LazySingleton{
private static LazySingleton instance;
private LazySingleton(){}
public static LazySingleton getInstance(){
if (instance == null)
instance = new LazySingleton();
return instance;
}
}
懒汉式双重检查锁:
使用volatile和多重检查,保证线程安全
public class LazyDoubleCheckSingleton{
private volatile static LazyDoubleCheckSingleton instance;
private LazyDoubleCheckSingleton(){}
public static LazyDoubleCheckSingleton getInstance(){
if (instance == null) {
synchronized (LazyDoubleCheckSingleton.class) {
if (instance == null)
instance = new LazyDoubleCheckSingleton();
}
}
return instance;
}
}
静态内部类:
在静态内部类中初始化创建对象,解决内存浪费问题和线程安全问题。
public class StaticClassSingleton{
private StaticClassSingleton(){}
public static StaticClassSingleton getInstance(){
return StaticClass,instance;
}
private static class StaticClass {
private static StaticClassSingleton instance = new StaticClassSingleton();
}
}
枚举类实现
单例的利弊
优点
- 保证该类有且只有一个实例
- 能get到指向该实例的全局访问点
缺点
- 违反了单一职责。因为该模式同时解决了两个问题
- 在多线程环境下需要处理,避免多个现场多次创建单例对象
- 单元测试时可能比较困难,许多测试框架基于继承来创建模拟对象。而单例模式下构造函数是私有的private,无法重写静态方法。