单例模式(Singleton mode)

一、概念

采取一定的方法保证在整个软件系统中 ,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。

一、应用场景

  • 只需要一个实例
    • 各种 Manager
    • 各种 Factory

三、设计模式写法(八种)

1.饿汉式 (静态常量)

class Singleton {
    private Singleton() {}

    private final static Singleton instance = new Singleton();

    public static Singleton getInstance() {
        return instance;
    }
}
1. 构造器私有化
2. 类的内部创建对象
3. 向外暴露一个静态公共方法(getInstance)
4. 代码实现

2. 饿汉式(静态代码块)

class Singleton {
    private Singleton() {}

    private    static Singleton instance;
    
    static {
        instance = new Singleton();
    }

    public static Singleton getInstance() {
        return instance;
    }
}

​ 小结:饿汉式说白了就是创建类的时候创建实例,这样可以保证线程安全,但是如果项目中没有用到就会造成资源浪费

3. 懒汉式(线程不安全)

class Singleton {
    private Singleton() {}

    private  static Singleton instance;

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

4. 懒汉式(线程安全,同步方法)

class Singleton {
    private Singleton() {}

    private  static Singleton instance;

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

这种方式会效率太低,不推荐使用

5. 懒汉式(线程安全,同步代码块)

class Singleton {
    private Singleton() {}

    private  static Singleton instance;

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

不能起到线程同步的作用,在实际中不能使用

6.双重检查(Double Check)

class Singleton {
    private Singleton() {}

    private volatile static Singleton instance;

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

两次 if (instance == null) 解决线程安全问题,同时解决懒加载问题,推荐使用

7.静态内部类

class Singleton {
    private Singleton() {}

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

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

这种方式 采用了类加载机制保证初始化实例时只有一个线程

避免了线程不安全,利用静态内部类特点实现延迟加载,效率高,推荐使用

8. 枚举

不仅能避免多线程同步问题,而且还能防止反序列话重新创建新的对象提倡使用

四、小结

  • 单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
  • 想实例化一个单例类的时候,使用相应的获取方法,而不是使用 new
  • 单例模式使用的场景
    1. 需要频繁进行创建和销毁的对象(各种池)
    2. 创建对象耗时过多或耗费资源过多,但是又经常用到的对象、工具类对象、频繁访问的数据库、文件的对象(数据源、session工厂等)

在实际使用中,多使用饿汉式(两种方法)、双重检查、静态内部类、枚举