转载请注明出处:http://blog.csdn.net/ljmingcom304/article/details/50454035
本文出自:【梁敬明的博客】
1.饿汉式
单例设计模式的写法存在很多种,常用的写法可分为懒汉式、饿汉式和登记式。
饿汉式是在类被加载时就已经被实例化,但是对于大的对象,实例化会很消耗资源,因此对于大对象不建议通过该种方式实现单例模式。
public class Single1 {
private static final Single1 s = new Single1();
private Single1() {
}
public static Single1 getInstance() {
return s;
}
}
2.懒汉式
饿汉式是在类被主动调用时才会被实例化,实现了类的延迟加载,此处通过两种方式来实现单例模式,一种是通过双重校验锁的方式,另一种是通过静态内部类的方式。
//双重校验锁
public class Single2 {
private static Single2 s = null;
private Single2() {
}
public static Single2 getInstance() {
if (s == null) {
synchronized (Single2.class) {
if (s == null) {
s = new Single2();
}
}
}
return s;
}
}
//静态内部类
public class Single3 {
private static class Single3Holder {
private static final Single3 INSTANCE = new Single3();
}
private Single3() {
}
public static Single3 getInsSingle3() {
return Single3Holder.INSTANCE;
}
}
3.登记式
不论懒汉式和饿汉式构造方法都是私有的,不允许被继承,失去类多态性,可将构造方法设置为被保护的,允许被子类继承。
public class Single4 {
private static Map<String, Single4> map = new HashMap<String, Single4>();
static {
Single4 s = new Single4();
map.put(Single4.class.getName(), s);
}
protected Single4() {
}
public static Single4 getInstance(String name) {
if (name == null) {
name = Single4.class.getName();
}
if (map.get(name) == null) {
try {
map.put(name, (Single4) Class.forName(name).newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
return map.get(name);
}
}
4.注意事项
当多个类加载器在加载类时,不同的类加载器会用不同的命名空间来区分同一个类,单例类会在多个类加载器环境下产生多个实例对象。
如果单例类实现类序列化接口,一个序列化的对象在每次反序列化时,都会创建一个新的对象,而不仅仅是对原对象的引用,为了避免该种情况的方式,应当在单例类中加入readResolve( )方法。