【偷学设计模式之创建型模式】单例 singleton ,单例只知道懒汉和饿汉??99%的人都知道了,你还不进来看?!

单例模式 singleton

可理解为:一个类只有一个实例.
单例模式相对来说比较简单,这里直接上代码直观感受一下。

实现

1.饿汉式

实现:

public class Singleton{
     
	private static final Singleton INSTANCE = new Singleton();
	private Singleton(){
     }
	public static Singleton getInstance(){
     
		return INSTANCE;
	}
}

使用:

public class JustTaskMain(){
     
	public static void main(String[] args){
     
		Singleton s = Singleton.getInstance();
	}
}

解释:

饿汉式写法,简单暴力,便于理解和编写

  1. 声明 private 无参构造方法,阻止外部实例化
  2. 声明唯一变量 INSTANCE 并实例化
  3. 提供静态方法访问获取 INSTANCE

这种写法的缺点在于,该单例类不管是否使用,在加载的时候就会进行实例化。
有点浪费资源,但是我们大多数情况并不 care 这种问题,所以这种简单易懂的写法也是推荐使用的。

2.懒汉式

实现:

public class Singleton{
     
	private volatile static Singleton INSTANCE;
	private Singleton(){
     }
	public static Singleton getInstance(){
     
		if(INSTANCE == null){
     
			synchronized(this){
     
            	if(INSTANCE == null){
     
					INSTANCE = new Singleton();
				}
        	}
		}
		return INSTANCE;
	}
}

使用:

public class JustTaskMain(){
     
	public static void main(String[] args){
     
		Singleton s = Singleton.getInstance();
	}
}

解释:

不同于饿汉式,懒汉式是比较完美的一种写法,当然其实现起来会比较复杂,要考虑多线程的情况。

  1. volatile 声明唯一实例,避免即时编译器指令重排导致可能发生的返回空对象的情况,即地址不为空,但还未实例化完成,此时 INSTANCE == null 返回的是 true 。
  2. synchronized 加双重判空机制,避免多线程环境下实例化出两个实例

相比饿汉式的写法,懒汉式在使用到时才会进行实例化,资源创建后置,是比较完美的一种写法,但是实现时需要注意的点比较多,尤其要考虑到多线程的情况。

3.内部类

实现:

public class Singleton {
     

    private Singleton() {
     
    }

    private static class InnerSingleton {
     
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
     
        return InnerSingleton.INSTANCE;
    }
}

使用:

public class JustTaskMain(){
     
	public static void main(String[] args){
     
		Singleton s = Singleton.getInstance();
	}
}

这里继续拓展单例类的设计,使用内部类的方式也可以做到使用时加载,且 JVM 会帮我们保证线程安全。

  1. 声明 InnerSingleton 并在其中声明外部类实例并初始化,利用类加载特性,在加载过程中不会加载内部类,而通过外部方法获取实现了使用时加载。

4.枚举

实现:

public enum Singleton {
     
    INSTANCE;
}

使用:

public class JustTaskMain(){
     
	public static void main(String[] args){
     
		Singleton s = Singleton.INSTANCE;
	}
}

利用枚举特性可以简单而优雅的实现单例,如上。

其缺点大概就是,通常来说我们都是使用 class ,而使用 enum 来定义单例感觉上有些别扭。

总结

以上 4 种单例的实现方式,在工业级别的使用上都是没有问题的,在实际的选用中结合你工程的代码风格,选择最合适的即可。

其实在现在我们实际开发中大多数也不用自己定义单例了,基本都由框架实现好了,如 Spring 框架等。

希望本文对你有所帮助,同时 欢迎添加个人微信 dyinggq 一起交流学习~~

我是 dying 搁浅 ,我始终期待与你的相遇。无论你是否期待,潮涨潮落,我仅且就在这里…

我们下期再见~
在这里插入图片描述

你可能感兴趣的:(偷学设计模式,设计模式,java)