sort:Java单例设计终极总结

概述

  • 单例模式最常见最常问到的设计模式
  • 单例设计模式(Singleton),即某个类在整个系统中只能有一个实例
  • 比如:代表JVM运行环境的Runtime类、代表某类信息的XxxClass、spring-IOC容器bean等
  • 关键点
    • 构造器私有化——保证外部不能随意new出新实例
    • 类自身提供该实例——通过静态变量或者静态方法
  • 设计分类
    • 按实例化时机可分为 饿汉式 和 懒汉式
    • 饿汉式特点是类加载时创建实例对象,不论是否会用到该实例。优点是简单、线程安全,缺点是资源占用。
    • 懒汉式则是延迟实例创建,在需要该类实例时才进行实例化,懒汉式缺点是需要注意线程安全问题。

饿汉式几种写法

最经典写法

public class Eager01 {
	//构造器私有化
	private Eager01() {}
	//public + static,提供外部直接类名获取
	//final 强调单例
	public static final Eager01 INSTANCE = new Eager01();
}

枚举写法

  • 使用枚举的单例设计以及成为现在最为优雅推崇的方式,优点很多
  • 优点:写法简单优雅; 线程安全; 可应对反射攻击; 序列化支持...
  • 唯一缺点:因为枚举类以及继承 Enum, 所以不能再继承拓展。严格的说,这算不上缺点..
  • 写法角度可以视为经典写法的简洁翻版
//理解:
//枚举类型即其实例为限定范围的几个,我们只提供一个,那么就是单例
public enum Eager2_enum {
	INSTANCE;
}

静态代码块写法

  • 适用于实例化时需要复杂逻辑处理的场景,比如加载属性文件等
  • 这些实例化处理在静态代码块中完成
public class Eager3_static_block {
	private Eager3_static_block() {}
	public static Eager3_static_block instance;
	static {
		//...其他操作,比如资源属性文件加载等
		instance = new Eager3_static_block();
	}
}
  • 单例最好加上 final,使用 private staic 方法
public class Eager3_static_block {
	private Eager3_static_block() {}
	public final static Eager3_static_block INSTANCE = init();
//	static {
//		//...其他操作,比如资源属性文件加载等
//		INSTANCE = new Eager3_static_block();
//	}
	private static Eager3_static_block init() {
		return new Eager3_static_block();
	}
}

懒汉式几种写法

简单延迟实例版 - 非线程安全

public class Lazy01 {
	//还是一样,构造器私有化
	private Lazy01() {}
	//静态私有变量
	private static Lazy01 instance;
	//提供public静态方法以获取实例
	public static Lazy01 getSingleton() {
		if(null == instance) {
			instance = new Lazy01();
		}
		return instance;
	}
}

线程安全 - 静态方法同步版

public class Lazy2 {
	//还是一样,构造器私有化
	private Lazy2() {}
	//静态私有变量
	private static Lazy2 instance;
	//提供public静态方法以获取实例,静态方法加锁
	public synchronized static Lazy2 getSingleton() {
		if(null == instance) {
			instance = new Lazy2();
		}
		return instance;
	}
}

性能与安全兼顾 - 双重检查同步锁版

public class Lazy3 {
	//还是一样,构造器私有化
	private Lazy3() {}
	//静态私有变量
	private static Lazy3 instance;
	//提供public静态方法以获取实例
	public static Lazy3 getSingleton() {
		if(null == instance) { //第一次检查,提高性能,只有第一次为null时才触发锁
			synchronized (Lazy2.class) {
				if(null == instance) { //第二次检查,安全考虑,防止线程同时通过第一次检查
					instance = new Lazy3();
				}
			}
		}
		return instance;
	}
}

优雅懒汉式 - 静态内部类版

  • 同使用枚举的懒汉式一样,属于优雅且受推崇的单例设计
  • 使用静态内部类,内部饿汉式,外部懒汉式,很巧妙,又避免了使用同步锁
public class Lazy4 {
	//还是一样,构造器私有化
	private Lazy4() {}
	//静态内部类
	private static class Inner {
		//饿汉式
		private static final Lazy4 INSTANCE = new Lazy4();
	}
	//外部懒汉式(调用此方法才会加载内部类,创建 INSTANCE 实例)
	public static Lazy4 getSingleton() {
		return Inner.INSTANCE;
	}
}
posted @ 2019-09-24 14:39  summaster  阅读(213)  评论(0编辑  收藏  举报