设计模式--创建者模式--单例模式

82 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

单例模式

单例模式设计到一个单一的类,该类负责创建自己的对象,并且有且只有一个对象能够被创建。并且该类提供了访问其唯一对象的方法,不需要客户端实例该对象

单例模式的结构

  1. 单例类:只能创建一个实例的类
  2. 访问类:使用实例的类

单例模式的实现方式

  1. 饿汉式:类加载时,就会创建该对象
  2. 懒汉式:类加载时不会创建该对象,首次使用该对象时才会创建

饿汉式实现方式

静态变量方式

public class Singleton {
    //私有构造方法
    private Singleton() {}

    //在成员位置创建该类的对象
    private static final Singleton instance = new Singleton();

    //对外提供静态方法获取该对象
    public static Singleton getInstance() {
        return instance;
    }
}

缺点:会造成内存浪费

静态代码块方式

public class Singleton{

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

缺点:同上,会造成内存浪费

枚举

public enum Singleton {
    INSTANCE;
}

说明:极力推荐,因为枚举类型是线程安全的,并且只会装载一次唯一一种不会被破坏的单例实现模式

懒汉式实现方式

方式1--线程不安全

public class Singleton{

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

问题: 会造成线程安全问题,可能会创建出多个对象

方式2--线程安全

public class Singleton{

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

问题:线程安全,但是执行效率低

方式3--双检查模式--线程安全

public class Singleton{

   private Singleton(){}
   
   //violatile是解决JVM在实例化对象的时候会进行优化和指令重排序操作
   priavte static volatile Singleton instance;
   
   public static Singleton getInstance(){
       if(instance == null){
           synchronized(Singleton.class){
               if(instance == null){
                   instance = new Singleton();
               }
           }
       }
       return instance;
   }
}

方式4--静态内部类

/**
 * 静态内部类方式
 */
public class Singleton {
​
    //私有构造方法
    private Singleton() {}
​
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
​
    //对外提供静态方法获取该对象
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

说明:静态内部类在外类加载时不会进行初始化,在调用才会初始化,而且类加载是线程安全的