单例模式,学习笔记

一、单例模式实现三要素:

●只能有一个实例。
  ◆构造器私有化

●自行创建这个实例
  ◆含有一个该类的静态变量来保存这个唯一的实例
●必须自行向整个系统提供这个实例;
  ◆对外提供获取该实例对象的方式:
  (1)直接暴露

  (2)用静态变量的get方法获取

二、单例模式分类

根据对象创建的时机不同,单例模式可以分为两类。一种是在类初始化的时候直接创建对象,称为饿汉式;另一种是在调用类静态方法时才创建对象,称为懒汉式。

三、饿汉式

饿汉式是线程安全的。

1.直接实例化饿汉式

public class Singleton {
    public static final Singleton INSTANCE = new Singleton();  //final修饰,强调这是一个单例
    private Singleton(){}

}

 2.枚举类饿汉式

public enum Singleton {
    INSTANCE;
}

3.静态代码块方式

public class Singleton {
    public static final Singleton INSTANCE;  //final修饰,强调这是一个单例
    static {
        INSTANCE = new Singleton();
    }
    private Singleton(){}

}

 这种方式适合于需要通过加载外部文件,来实例化单例对象属性的时候。

例如:

public class Singleton1 {
    public static final Singleton1 INSTANCE;
    private String name;
    
    static {
        INSTANCE = new Singleton1();
        try {
            InputStream inputStream = Singleton1.class.getClassLoader().getResourceAsStream("singleton.properties");
            Properties properties = new Properties();
            properties.load(inputStream);
            String name = properties.getProperty("singleton1.name");
            INSTANCE.name = name;
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    
    private Singleton1(){}

    public String getName() {
        return name;
    }
}
View Code

四、懒汉式

方式一:

public class Singleton {
    public static Singleton instance;
    private Singleton(){

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

注:此方式有线程安全问题,只适用于单线程环境。

方式二:同步代码块

public class Singleton {
    public static Singleton instance;
    private Singleton(){

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

注:此方式虽然解决了线程安全问题,但是效率低,不推荐使用

方式三:

public class Singleton {
    public static Singleton instance;
    private Singleton(){

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

 效率比前一种高,推荐使用

方式四:静态内部类(强烈推荐使用)

public class Singleton {
    private Singleton(){

    }

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

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

注:

在内部类被加载和初始化时,才创建工 NSTANCE实例对象。

静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的。因为是在内部类加载和初始化时,创建的,因此是线程安全的。

原文地址:https://www.cnblogs.com/bear7/p/13403382.html