设计模式之单例模式

确保一个类在任何情况下都只有一个实例,并提供一个全局访问点

结构

单例类:只能创建一个实例的类

访问类:使用单例类的类

优缺点

优点:

1、在内存里只有一个实例,减少了内存的开销

2、避免对资源的多重占用

缺点:

没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化

特点

1.单例类只能有一个实例

2.单例类必须自己创建自己的唯一实例

3.单例类必须给所有其他对象提供这一实例

使用场景

1.有频繁的实例化后又销毁的情况,适合考虑使用单例模式,如记录日志的log对象

2.创建对象需要消耗过多的系统资源,但又经常用到的资源,如数据库连接

创建模式

饿汉式

在该类初始化的时候就创建实例对象,线程是安全的

java 复制代码
public class Singleton {  
    // 在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快  
    private static Singleton instance = new Singleton();  
  
    // 私有化构造函数,防止外部创建对象  
    private Singleton(){}  
  
    // 提供一个全局访问点  
    public static Singleton getInstance(){  
        return instance;  
    }  
}

饿汉式单例模式的优点是线程安全且效率高。由于实例在类加载时就创建了,所以获取对象的速度快。此外,由于构造函数是私有的,外部无法创建实例,因此可以保证只有一个实例

缺点:

饿汉式单例模式的缺点是可能会造成内存空间的浪费。如果该实例需要消耗大量的内存,且在程序的生命周期内可能不会使用到这个实例,那么就会造成内存空间的浪费

懒汉式

首次使用单例实例的时候创建,之后使用时再判断单例实例是否已创建,如果没有则创建实例

java 复制代码
public class Singleton {  
    // 私有静态变量,用于保存单例对象  
    private static Singleton instance;  
  
    // 私有化构造函数,防止外部创建对象  
    private Singleton(){}  
  
    // 在第一次使用时,通过静态代码块创建实例  
    private static void initializeInstance() {  
        instance = new Singleton();  
    }  
  
    // 提供一个全局访问点  
    public static Singleton getInstance(){  
        if (instance == null) {  
            initializeInstance();  
        }  
        return instance;  
    }  
}

instance变量在第一次调用getInstance()方法时才创建,因此线程是不安全的。为了实现线程安全,可以使用双重检查锁定、静态初始化块、枚举方式

优点:

只有在需要使用实例时才创建。这可以节省内存空间,特别是对于那些在程序生命周期中不一定需要的实例

双重检查锁定

java 复制代码
public class Singleton {  
    // 使用volatile关键字,确保该变量在多线程环境下保持可见性  
    private volatile static Singleton instance;  
  
    // 私有化构造函数,防止外部创建对象  
    private Singleton(){}  
  
    // 在第一次使用时,通过静态代码块创建实例  
    private static void initializeInstance() {  
        instance = new Singleton();  
    }  
  
    // 提供一个全局访问点  
    public static Singleton getInstance(){  
        // 第一次检查,如果instance不为null,说明实例已经被初始化,直接返回实例即可  
        if (instance == null) {  
            synchronized (Singleton.class) {  
                // 第二次检查,如果instance为null,说明实例还没有被初始化,需要进入同步块进行初始化  
                if (instance == null) {  
                    instance = new Singleton();  
                }  
            }  
        }  
        return instance;  
    }  
}

instance变量使用volatile关键字修饰,以确保在多线程环境下保持可见性。双重检查锁定通过两次检查instance变量的值是否为null来实现线程安全

静态初始化块

java 复制代码
public class Singleton {  
    // 私有静态变量,用于保存单例对象  
    private static Singleton instance;  
  
    // 私有化构造函数,防止外部创建对象  
    private Singleton(){}  
  
    // 使用静态初始化块来创建实例  
    static {  
        instance = new Singleton();  
    }  
  
    // 提供一个全局访问点  
    public static Singleton getInstance(){  
        return instance;  
    }  
}

instance变量在类加载时创建实例,因此它是线程安全的。

优点:避免了在第一次调用getInstance()方法时进行同步的开销;线程安全的,可以确保只创建一个实例

缺点:会造成类加载的开销

枚举方式

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

java 复制代码
public enum Singleton {  
    INSTANCE;  
  
    // 单例对象  
    private Singleton instance;  
  
    // 私有方法,用于创建实例  
    private void createInstance() {  
        instance = new Singleton();  
    }  
  
    // 公共方法,用于获取实例  
    public Singleton getInstance() {  
        if (instance == null) {  
            synchronized (Singleton.class) {  
                if (instance == null) {  
                    createInstance();  
                }  
            }  
        }  
        return instance;  
    }  
}

instance变量在枚举类型被加载时创建实例,因此它是线程安全的。枚举类型在Java中是线程安全的,并且只有一个实例。getInstance()方法用于获取实例,它首先检查instance变量是否为null,如果是null,则进入同步块,再次检查instance变量是否为null,如果是null,则创建一个新的实例

优点:具有更高的性能和更少的内存占用;使用枚举实现的单例模式更加简单和安全

缺点:只能创建单一的实例,无法实现多个实例的创建和管理

相关推荐
2的n次方_2 分钟前
二维费用背包问题
java·算法·动态规划
皮皮林5513 分钟前
警惕!List.of() vs Arrays.asList():这些隐藏差异可能让你的代码崩溃!
java
莳光.3 分钟前
122、java的LambdaQueryWapper的条件拼接实现数据sql中and (column1 =1 or column1 is null)
java·mybatis
程序猿麦小七8 分钟前
基于springboot的景区网页设计与实现
java·spring boot·后端·旅游·景区
weisian15114 分钟前
认证鉴权框架SpringSecurity-2--重点组件和过滤器链篇
java·安全
蓝田~16 分钟前
SpringBoot-自定义注解,拦截器
java·spring boot·后端
.生产的驴19 分钟前
SpringCloud Gateway网关路由配置 接口统一 登录验证 权限校验 路由属性
java·spring boot·后端·spring·spring cloud·gateway·rabbitmq
v'sir32 分钟前
POI word转pdf乱码问题处理
java·spring boot·后端·pdf·word
提高记忆力41 分钟前
SpringBoot整合FreeMarker生成word表格文件
java·spring
JDS_DIJ41 分钟前
RabbitMQ
java·rabbitmq·java-rabbitmq