设计模式--单例模式

设计模式--单例模式

单例模式应该算最简单的设计模式,但在Java中单例模式还是有不少坑的。
个人对单例的理解是全局中有且仅有一个的实例,不能通过其他方式构造,只能通过特定方法访问,因此单例的构造器通常是私有的,在内部会创建这个唯一实例,且会提供一个公开的方法用于访问这个实例

饿汉式

类初始化时直接加载,没有线程安全问题,但没有实现lazy loading

public class Singleton {
    private static Singleton instance = new Singleton();
    
    //私有化构造器
    private Singleton() {}
    
    //访问方法
    public static Singleton getInstance() {
        return instance;
    }
}

懒汉式,不加锁

不加锁,在多线程环境下会new出多个对象

public class Singleton{
    private static Singleton instance;
    
    private Singleton(){} 
    
    public static Singleton getInstance(){
        if(instance == null){
            instance = new Singleton(); 
        }
        return instance;
    }
}

懒汉式,加锁的双重校验

比较常见的一种写法,采用加锁的双重校验方式,不过个人不是很喜欢这种写法,毕竟代码比较长

public class Singleton {
  private static volatile Singleton instance;

  private Singleton() {}

  public Singleton getInstance() {
    if (instance == null) {
      synchronized (Singleton.class) {
        if (instance == null) {
          instance = new Singleton();
        }
      }
    }
    return instance;
  }
}

懒汉式,静态内部类

比较喜欢这种写法,和饿汉式比较类似,但通过类加载机制避免Singleton类初始化时加载这个单例,仅在需要调用实例的时候加载

public class Singleton {

    private Singleton() {}

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

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

枚举

这个比较爽,3行代码解决,但感觉用的比较少。。

public enum Singleton {
  INSTANSE
}

使用jad反编译代码可以看出枚举是在静态块中加载,属于饿汉式

package test;


public final class Singleton extends Enum
{

    private Singleton(String s, int i)
    {
        super(s, i);
    }

    public static Singleton[] values()
    {
        Singleton asingleton[];
        int i;
        Singleton asingleton1[];
        System.arraycopy(asingleton = ENUM$VALUES, 0, asingleton1 = new Singleton[i = asingleton.length], 0, i);
        return asingleton1;
    }

    public static Singleton valueOf(String s)
    {
        return (Singleton)Enum.valueOf(test/Singleton, s);
    }

    public static final Singleton INSTANSE;
    private static final Singleton ENUM$VALUES[];

    static 
    {
        INSTANSE = new Singleton("INSTANSE", 0);
        ENUM$VALUES = (new Singleton[] {
            INSTANSE
        });
    }
}
posted @ 2019-10-06 21:12  lz_0011  阅读(110)  评论(0编辑  收藏  举报