1. 什么是单例模式👀
单例模式属于创建型模式,⼀个单例类在任何情况下都只存在⼀个实例, 构造⽅法必须是私有的、由⾃⼰创建⼀个静态变量存储实例,对外提供⼀ 个静态公有⽅法获取实例。 优点是内存中只有⼀个实例,减少了开销,尤其是频繁创建和销毁实例的 情况下并且可以避免对资源的多重占⽤。缺点是没有抽象层,难以扩展, 与单⼀职责原则冲突。
2. 单例模式的实现🏃♂️🏃♀️
单例模式的实现主要有两种类型,一种是懒汉式,一种是饿汉式。其他实现方式都是基于这两种的变形。
实现要点:
- 只能类本身创建实例对象
- 只有一个实例对象
2.1 懒汉式
这种⽅式在单线程下使⽤没有问题,对于多线程是⽆法保证单例的,这⾥列出来是为了和后⾯使⽤锁保证线程安全的单例做对比。
🧡优点: 懒加载,用到了再创建
💔缺点: 线程不安全
2.1.1 懒汉式-基础实现⭐⭐
/**
* 懒汉单例
* @Author Aldebaran α
* @Date 2022/5/20 15:47
*/
public class LazySingle {
private LazySingle lazySingle ;
/**
* 单例模式必定关闭构造函数,只能由自己创建
*/
private LazySingle(){
}
/**
* 懒汉式单例
* 用到了再创建
* @return
*/
public LazySingle getInstance(){
if(lazySingle == null){
return new LazySingle();
}
return lazySingle;
}
}
2.1.2 懒汉式—多线程-双检锁⭐⭐⭐
/**
* 多线程-双检锁
* @return
*/
public LazySingle getMultiThreadInstance(){
if (lazySingle == null) {
synchronized (LazySingle.class) {
if (lazySingle == null) {
lazySingle = new LazySingle();
}
}
}
return lazySingle;
}
2.2 饿汉式
饿汉式单例模式,顾名思义,类⼀加载就创建对象,这种⽅式⽐较常⽤,但容易产⽣垃圾对象,浪费内存空间。
🧡优点: 线程安全(o゚v゚)ノ,没有加锁(✿◡‿◡),执⾏效率较⾼(❁´◡`❁)
💔缺点: 不是懒加载,类加载时就初始化,浪费内存空间
2.2.1 饿汉式—基础实现⭐⭐⭐
/**
* 饿汉式单例
* @Author Aldebaran α
* @Date 2022/5/20 15:51
*/
public class HungrySingle {
// 提前准备好
private final HungrySingle hungrySingle = new HungrySingle();
/**
* 单例模式必定关闭构造函数,只能由自己创建
*/
private HungrySingle(){
}
public HungrySingle getInstance(){
return hungrySingle;
}
}
2.2.2 饿汉式—静态内部类⭐⭐⭐
/**
* @Author Aldebaran α
* @Date 2022/5/25 10:15
*/
public class StaticInnerClass {
/**
* 关闭外部构造
*/
private StaticInnerClass() {
}
/**
* 对外提供获取实例的公共⽅法
* @return
*/
public static StaticInnerClass getInstance() {
return InnerClass.INSTANCE;
}
/**
* 定义静态内部类
*/
private static class InnerClass {
private final static StaticInnerClass INSTANCE = new StaticInnerClass();
}
}
2.2.3 饿汉式—类加载⭐⭐⭐⭐
/**
* 单例模式 使用了类加载机制 - 饿汉式
* @Author Aldebaran α
* @Date 2021/10/26 10:41
*/
public final class SingleUtil {
public static SingleUtil SINGLE_UTIL;
static {
new SingleUtil();
}
/**
* 关闭外部构造
*/
private SingleUtil(){
SINGLE_UTIL = this;
}
public void say(){
System.out.println("单例模式!!!!!!!");
}
}
2.2.4 饿汉式—枚举⭐⭐⭐⭐⭐
/**
* @Author Aldebaran α
* @Date 2022/5/25 10:42
*/
public enum SingleEnum {
INSTANCE;
public void say(){
System.out.println("枚举单例!!!");
}
public static void main(String[] args) {
INSTANCE.say();
}
}
3. 单例模式的使用👩🏫👨🏫
- 做统计,例如网站访问人数的统计,接口访问次数的统计。
- 配置文件访问,例如程序需要一个类去读取配置文件存下来。避免反复创建新对象,反复读取,造成不必要的IO操作。
- 线程池单例。
- spring容器管理的对象也都是单例的。