1 概念
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。 实现方法: (1) 构造器私有化 。 (2) 类的内部创建对象。 (3) 向外暴露一个静态的公共方法。
2 饿汉式
优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。 缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费
public class HungrySingleton {
private static final HungrySingleton hungrySingleton
= new HungrySingleton();
private HungrySingleton() {
}
public static HungrySingleton
getInstance(){
return hungrySingleton
;
}
}
3 懒汉式
懒汉式单例的特点是:被外部类调用的时候内部类才会加载
3.3 类锁
public class LazySingleton {
private static LazySingleton lazySingleton
= null
;
private LazySingleton() {
}
public static synchronized LazySingleton
getInstance() {
if (lazySingleton
== null
) {
lazySingleton
= new LazySingleton();
}
return lazySingleton
;
}
}
3.2 双重检查
public class LazyDoubleCheckSingleton {
private static LazyDoubleCheckSingleton lazyDoubleCheckSingleton
= null
;
private LazyDoubleCheckSingleton() {
}
public static LazyDoubleCheckSingleton
getInstance() {
if (lazyDoubleCheckSingleton
== null
) {
synchronized (LazyDoubleCheckSingleton
.class) {
if (lazyDoubleCheckSingleton
!= null
) {
return lazyDoubleCheckSingleton
;
}
lazyDoubleCheckSingleton
= new LazyDoubleCheckSingleton();
return lazyDoubleCheckSingleton
;
}
}
return lazyDoubleCheckSingleton
;
}
}
3.3 内部类
public class LazyInnerClassSingleton {
private LazyInnerClassSingleton() {
}
public static LazyInnerClassSingleton
getInstance() {
return Lazyholder
.LAZY
;
}
private static class Lazyholder {
private static final LazyInnerClassSingleton LAZY
= new LazyInnerClassSingleton();
}
}
PS: 反射破坏单例模式
public class ReflectDestoryDemo {
public static void main(String
[] args
) throws Exception
{
Class
<?> clazz
= LazyDoubleCheckSingleton
.class;
Constructor
<?> constructor
= clazz
.getDeclaredConstructor();
constructor
.setAccessible(true);
Object o1
= constructor
.newInstance();
LazyDoubleCheckSingleton o2
= LazyDoubleCheckSingleton
.getInstance();
System
.out
.println(o1
== o2
);
}
}
4 注册式单例
public class ContainerSingleton {
private ContainerSingleton() {
}
private static Map
<String, Object> ioc
= new ConcurrentHashMap<>();
public static Object
getBean(String className
) {
synchronized (ioc
) {
if (!ioc
.containsKey(className
)) {
Object obj
= null
;
try {
obj
= Class
.forName(className
).newInstance();
ioc
.put(className
, obj
);
} catch (Exception e
) {
e
.printStackTrace();
}
}
return ioc
.get(className
);
}
}
}
5 JDK 源码