Inspired by Effective Java.
Singleton模式是在编程实践中应用最广泛的几种设计模式之一。以前知道的,实现单例的方法只有两种,懒汉,饿汉。刚刚在读《Effective Java的时候》学到一种新的更好的方法(E):单元素的枚举类型。同时通过网上资料也知道了其他两种方法(C、D)。枚举单例从Java中从1.5版本开始支持,其他语言在验证后说明。
/**
* 枚举实现单利
* 1.优点 不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
* 2.缺点 失去了类的一些特性,没有延迟加载,用的人也太少了~~
*/
enum SingletonC{
INSTANCE;
public void say(){
System.out.println(" hello enum");
}
}
/*******************下面的 单例生成方式 可以通过 反射和序列化 生成新的对象*************************************/
/**
* 恶汉模式单利
* 1.优点: 因为加载类的时候就创建实例,所以线程安全(多个ClassLoader存在时例外)。
* 2.缺点: 是不能延时加载。
*/
class MaYun {
public static final MaYun instance = new MaYun(); //静态的final的MaYun
private MaYun() { //MaYun诞生要做的事情
}
public void splitAlipay() {
System.out.println("do something");
}
}
class MaYun1 {
private static MaYun1 instance = new MaYun1();
private static MaYun1 getInstance() {
return instance;
}
private MaYun1() {
}
public void splitAlipay() {
System.out.println("do something");
}
}
class MaYun2 {
private static MaYun2 instanceM = null;
static {
instanceM = new MaYun2();
}
private MaYun2() {
//MaYun诞生要做的事情
}
public static MaYun2 getInstance() {
return instanceM;
}
public void splitAlipay() {
System.out.println("do something");
}
}
/**
* 懒汉单例模式
* 1.优点: 延时加载 类加载时不初始化
* 2.缺点: 需要加锁才能实现多线程同步,但是效率会降低。
*/
class MaYunLazy {
private static MaYunLazy instance = null;
private MaYunLazy() {
}
public static MaYunLazy getInstance() {
if (instance == null) {
instance = new MaYunLazy();
}
return instance;
}
public void splitAlipay() {
System.out.println("do something");
}
}
class MaYunLazy1 {
private static MaYunLazy1 instance = null;
private MaYunLazy1() {
}
public static synchronized MaYunLazy1 getInstance() {
if (instance == null) {
instance = new MaYunLazy1();
}
return instance;
}
public void splitAlipay() {
System.out.println("do something");
}
}
/**
* 内部类单例模式
* 延迟加载,减少内存开销。因为用到的时候才加载,
* 避免了静态field在单例类加载时即进入到堆内存的permanent代而永远得不到回收的缺点(大多数垃圾回收算法是这样)。
*
*/
/**
* 内部类单例模式
* 延迟加载,减少内存开销。因为用到的时候才加载,
* 避免了静态field在单例类加载时即进入到堆内存的permanent代而永远得不到回收的缺点(大多数垃圾回收算法是这样)。
*/
class MaYuninner {
private static class SigletonHolder {
private static final MaYuninner instance = new MaYuninner();
}
public static final MaYuninner getInstance() {
return SigletonHolder.instance;
}
private MaYuninner() {
}
public void splitAlipay() {
System.out.println("do something");
}
}
/**
* 双重锁 校验 单例模式
* 麻烦,在当前Java内存模型中不一定都管用,某些平台和编译器甚至是错误的,
* 因为instance = new MaYunSyncD()这种代码在不同编译器上的行为和实现方式不可预知。
*
*/
class MaYunSyncD {
private volatile static MaYunSyncD instance;
private MaYunSyncD (){}
public static MaYunSyncD getInstance() {
if (instance == null) {
synchronized (MaYunSyncD.class) {
if (instance == null) {
instance = new MaYunSyncD();
}
}
}
return instance;
}
}