资讯 更多 >>
头一次见单例模式讲的如此透彻_每日信息
麦当劳啤酒是什么? 天天百事通
焦点速看:lol的fps是越高越好吗_lo...
成都上空惊现UFO?天文科普学者:可...
手碟奏响央视《经典咏流传》,经典...
二线城市坐网约车有感:电动车普及...
数控G96怎么用(数控g96) 天天快播报
会计主要干些什么_会计主要做哪些工作
河南地级市市委书记名单_河南地级市
荠菜的功效与作用图片和吃法_荠菜的...
动态更多 >>
你们,温暖了2021
西安市新增27个中风险地区 目前有1...
广西新增本土确诊病例1例
哈尔滨市全域均为低风险地区
寒潮将影响我国中东部地区 四川盆...
昆明至哈尔滨一航班发现1名入境复阳...
陕西研考:封控区内考生在原报考点...
北京今日最高气温仅5℃ 明起强冷空...
那年今日 | 历史上的12月22日发生...
我要找债主
会展 更多 >>
美籍酿酒师在崇礼:中国是第二故乡...
河南项城报告2名疑似新冠肺炎病例 ...
浙江绍兴确诊病例首次零新增 上虞...
广西东兴实行全员居家隔离 启动口...
新疆全方位推进乡村振兴 “富春山...
云南瑞丽市主城区全员核酸检测结果...
内蒙古满洲里累计治愈出院本土确诊...
孙海洋夫妻驱车山东阳谷:还在为孙...
大国工匠追梦“玉米强国”40载:用...
让南海“海洋热带雨林”斑斓多彩
专题报道 
当前位置: 资讯 > >> 正文
 
头一次见单例模式讲的如此透彻_每日信息
来源:博客园     时间:2023-06-23 12:29:46

简介

单例模式是一种常用的软件设计模式,用于创建类型。通过单例模式的方法创建的类在当前进程中只有一个实例。单例模式的类只能允许一个实例存在。单例模式的作用是保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个。

组成部分:


(资料图片)

私有化构造方法。私有化内部实例。公有静态方法用来获取内部实例。优缺点

单例模式的优点有:

提供了对唯一实例的受控访问,可以保证对象的唯一性和一致性。减少了内存开销,避免了频繁的创建和销毁对象。避免了对资源的多重占用,例如文件操作、数据库连接等。

单例模式的缺点有:

不支持继承和多态,违反了单一职责原则,一个类应该只关心内部逻辑,而不关心外部如何实例化。不易扩展,如果需要创建多个实例,就需要修改代码,违反了开闭原则,一个类应该对扩展开放,对修改关闭。不支持有参数的构造函数,如果需要传递参数,就需要修改方法或者定义其他方法。可能存在反射或者反序列化攻击,破坏单例的唯一性。应用场景

单例模式适用于以下场景:

需要频繁创建和销毁的对象,例如缓存、线程池、注册表等。需要控制资源的访问,例如文件操作、数据库连接等。需要保证对象的唯一性和一致性,例如配置信息、全局变量等。Java 代码示例

在 Java 中,有五种不同的单例实现方法。其中包括饿汉式、懒汉式、双检锁、静态内部类和枚举类。单例模式的五种实现原理分别是饿汉式、懒汉式、双重检测、静态内部类和枚举类。它们各自的优缺点如下:

饿汉式:原理是在类加载的时候,就创建并初始化一个静态的实例对象,然后通过一个静态的方法返回这个实例。优点是线程安全,不需要加锁;缺点是不支持延迟加载,可能会浪费资源。
public class Singleton {    private Singleton() {}    private static Singleton instance;    public static synchronized Singleton getInstance() {        if (instance == null) {            instance = new Singleton();        }        return instance;    }}
懒汉式:原理是在第一次调用获取实例的方法时,才创建并初始化一个静态的实例对象,然后返回这个实例。为了保证线程安全,需要给获取实例的方法加上synchronized关键字。优点是支持延迟加载,节省资源;缺点是线程不安全,需要加锁,影响性能。
public class Singleton {    private Singleton() {}    private static final Singleton instance = new Singleton();    public static Singleton getInstance() {        return instance;    }}
双重检测:原理是在第一次调用获取实例的方法时,先判断静态的实例对象是否为空,如果为空,则进入同步代码块,再判断一次是否为空,如果为空,则创建并初始化一个静态的实例对象,然后返回这个实例。为了防止指令重排序导致空指针异常,需要给静态的实例对象加上volatile关键字。优点是线程安全,支持延迟加载,不需要加锁;缺点是可能会出现空指针异常,需要使用 volatile 关键字防止指令重排序。
public class Singleton {    private Singleton() {}    private static volatile Singleton instance;    public static Singleton getInstance() {        if (instance == null) {            synchronized (Singleton.class) {                if (instance == null) {                    instance = new Singleton();                }            }        }        return instance;    }}
静态内部类:原理是利用了 Java 静态内部类的特性,即外部类加载时不会加载内部类,只有在使用到内部类时才会加载。因此,在第一次调用获取实例的方法时,才会加载静态内部类,并创建并初始化一个静态的实例对象,然后返回这个实例。优点是线程安全,支持延迟加载,不需要加锁;缺点是不能防止反射或者反序列化攻击。
public class Singleton {    private Singleton() {}    private static class Instance {        private static final Singleton instance = new Singleton();    }    public static Singleton getInstance() {        return Instance.instance;    }}
枚举类:原理是利用了Java枚举类型本身的特性,即枚举类型在加载时就会创建所有的枚举常量,并且保证了线程安全性和唯一性。因此,在调用获取实例的方法时,直接返回枚举常量即可。优点是线程安全,简单易用,可以防止反射或者反序列化攻击;缺点是不支持延迟加载,不能继承其他类。
public enum Singleton {     INSTANCE;}

这些不同的实现方式有不同的适用场景,需要根据具体的需求和条件来选择。在这里,我只能给出一些个人的看法,仅供参考。

如果对内存资源比较敏感,或者单例对象不需要频繁使用,可以考虑使用懒汉式或者双重检测,因为它们支持延迟加载,可以节省资源。如果对性能比较敏感,或者单例对象需要频繁使用,可以考虑使用饿汉式或者静态内部类,因为它们不需要加锁,可以提高效率。如果对安全性比较敏感,或者需要防止反射或者反序列化攻击,可以考虑使用枚举类,因为它可以保证实例的唯一性和不可变性。如果对简洁性比较敏感,或者不需要继承其他类,可以考虑使用枚举类,因为它是最简单的实现方式。

个人来说在编码效率和可维护性上我比较倾向于使用静态内部类的实现方式,既能保证线程安全性,又能支持延迟加载。

Spring 代码示例

在 Spring 框架中,Spring 默认使用单例模式来创建和管理 Bean 对象,但是可以通过 @Scope("singleton")注解来指定 Bean 对象的作用域。

@Scope("singleton"):表示该Bean对象是一个单例对象,在整个Spring容器中只有一个实例。@Scope("prototype"):表示该Bean对象是一个原型对象,在每次请求时都会创建一个新的实例。@Scope("request"):表示该Bean对象的作用域是一个HTTP请求,在同一个请求中只有一个实例。@Scope("session"):表示该Bean对象的作用域是一个HTTP会话,在同一个会话中只有一个实例。总结

单例模式是一种简单而常用的设计模式,它可以保证一个类只有一个实例,并提供一个全局访问点。单例模式有多种实现方式,各有优缺点。单例模式可以节约系统资源,避免资源冲突,保证对象的唯一性和一致性。但是单例模式也有不利于继承和扩展的缺点,以及可能存在的安全隐患。在使用单例模式时,需要根据具体情况和需求选择合适的方法,并注意避免潜在的问题。

关注公众号【waynblog】每周分享技术干货、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力!

关键词:

热门推荐
猜你喜欢