单例模式是为了确保一个类中只有一个实例,并为整个系统提供一个全局访问点的一种方法。
单例模式所适用的场景:需要生成唯一序列的环境;需要频繁实例化然后销毁的对象;创建对象时耗时过多或者耗资源过多,但又经常用到的对象;过多或者耗资源过多,但又经常用到的对象。
单例模式的组成部分:私有的构造方法;指向自己实例的私有静态引用;以自己实例为返回值的静态的公有方法。
可以通过以下几种方式实现单例模式:
1.饿汉式
饿汉式单例在单例类被加载时候,就实例化一个对象并交给自己的引用。饿汉式单例是安全的,调用效率高,但不能延时加载。
示例代码:

public class Individual1 {
	//饿汉式单例
	//实例化这个类
	private static final Individual1 ONE=new Individual1();
	//隐藏构造器
	private Individual1(){
		
	}
	//创建静态工厂方法,让外部可以获取示例
	public static Individual1 getInstance(){
		return ONE;
	}
}

2.懒汉式
懒汉式单例是线程安全的,调用效率不高,但能延时加载,只有在真正使用的时候才会实例化一个对象并交给自己的引用。与饿汉式相比,懒汉式的资源利用率更高,而饿汉式的速度和反应时间更快。
示例代码:

public class Individual2 {
	//懒汉式单例
	//类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)
	private static Individual2 two;
	//隐藏构造器
	private Individual2(){
		
	}
	//方法同步,调用效率低
	//创建静态工厂方法 ,让外部可以获取实例
	public static synchronized Individual2 getInstance(){
		if(two == null){
			two=new Individual2();
		}
		return two;
	}
}

3.静态内部类
静态内部类实现单例,该单例是线程安全的,调用效率高,可以延时加载。
示例代码:

public class Individual3 {
	//静态内部类
	private static class SingletonClass{
		private static final Individual3 three=new Individual3();
	}
	// 私有化构造器
	private Individual3() {
	
	}
	//静态工厂方法
	public static Individual3 getInstance(){
		return SingletonClass.three;
	}
}

4.枚举类
枚举类实现单例是线程安全的,调用效率高,不能延时加载,可以天然的防止反射和反序列化调用
示例代码:

public class Individual4 {
	//枚举类
	//私有化构造器
	private Individual4(){
		
	}
	//使用枚举
	private static enum Singletons{
		FOUR;
		
		private Individual4 singletons;
		//JVM会保证此方法绝对只调用一次
		private Singletons(){
			singletons=new Individual4();
		}
		public Individual4 getInstance(){
			return singletons;
		}
	}
	//静态工厂方法
	public static Individual4 getInstance(){
		return Singletons.FOUR.getInstance();
	}
}

5.Double CheckLock实现单例
Double CheckLock也就是双重判断机制,由于JVM底层模型原因,偶尔会出现问题,不建议使用,作为了解就可以了。
示例代码:

public class Individual5 {
    private volatile static Individual5 five;
	
	//私有化构造器
	private Individual5(){
		
	}
	//静态工厂方法,双重锁判断机制
	public static Individual5 newInstance(){
		if(five == null){
			synchronized (Individual5.class){
				if(five == null){
					five =new Individual5();
				}
			}
		}
		return five;
	}
}

6.如何选择
当单例对象占用资源少,不需要延时加载时枚举好于饿汉;单例对象占用资源多,需要延时加载时静态内部类好于懒汉式。

更多推荐

Java单例模式