设计模式(五):单例模式

1.定义

对于系统中的某些类来说,只有一个实例很重要,例如,一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。

单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式是一种对象创建型模式。

2.结构

单例模式包含如下角色:

  • Singleton:单例
    在这里插入图片描述

3.分析

  • 单例模式的目的是保证一个类仅有一个实例,并提供一个访问它的全局访问点。
  • 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它,并为设计及开发团队提供了共享的概念。
  • 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。
  • 允许可变数目的实例。我们可以基于单例模式进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例,同时解决了单例单例对象共享过多有损性能的问题。
  • 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。同时单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法。
  • 现在很多面向对象语言(如Java、C#)的运行环境都提供了自动垃圾回收的技术,因此,如果实例化的共享对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致共享的单例对象状态的丢失。

4.适用环境

  • 系统只需要一个实例对象
  • 客户调用类的单个实例只允许使用一个公共的全局访问点

5.模式实现

  • 饿汉式单例(线程安全)
class EagerSingleton {

    private static final EagerSingleton INSTANCE = new EagerSingleton();

    private EagerSingleton() {}

    public static EagerSingleton getInstance() {
        return INSTANCE;
    }
}

  • 懒汉式单例(线程不安全)
class UnsafeLazySingleton {

    private static UnsafeLazySingleton INSTANCE = null;

    private UnsafeLazySingleton() {}

    public static UnsafeLazySingleton getInstance() {
        if (null == INSTANCE) {
            INSTANCE = new UnsafeLazySingleton();
        }
        return INSTANCE;
    }
}
  • 懒汉式+Synchronized (线程安全)
class SafeLazySingleton {

    private static SafeLazySingleton INSTANCE = null;

    private SafeLazySingleton() {}

    /**
     * synchronized进行线程锁定
     */
    public static synchronized SafeLazySingleton getInstance() {
        if (null == INSTANCE) {
            INSTANCE = new SafeLazySingleton();
        }
        return INSTANCE;
    }
}
  • 懒汉式+DCL + Volatile (线程安全)
class AdvanceSingleton {

    /**
     * volatile屏蔽JVM所做的一些代码优化,确保可见性
     */
    private static volatile AdvanceSingleton INSTANCE = null;

    private AdvanceSingleton() { }

    public static AdvanceSingleton getInstance() {
        // 双重检查锁定(Double-Check Locking)确保线程安全
        if (INSTANCE == null) {
            synchronized (AdvanceSingleton.class) {
                if (INSTANCE == null) {
                    INSTANCE = new AdvanceSingleton();
                }
            }
        }
        return INSTANCE;
    }
}
  • Initialization Demand Holder (IoDH):静态嵌套类(线程安全)
class IoDHSingleton {
    private IoDHSingleton() {
    }

    private static class HolderClass {
        // 由JVM来保证其线程安全性,在加载HolderClass时确保该成员变量只能初始化一次
        private final static IoDHSingleton INSTANCE = new IoDHSingleton();
    }

    /**
     * 没有任何线程锁定,其性能不会造成任何影响
     */
    public static IoDHSingleton getInstance() {
        return HolderClass.INSTANCE;
    }
}
说明:通过使用IoDH,我们既可以实现延迟加载,又可以保证线程安全,不影响系统性能,不失为一种较好的Java语言单例模式实现方式(其缺点是与编程语言本身的特性相关,很多面向对象语言不支持IoDH)
  • CAS式单例(线程安全)
class CASSingleton {

    private static final AtomicReference<CASSingleton> INSTANCE = new AtomicReference<CASSingleton>();

    private CASSingleton() {}

    public static CASSingleton getInstance() {
        for(;;) {
            CASSingleton singleton = INSTANCE.get();
            if (null != singleton) {
                return singleton;
            }
            singleton = new CASSingleton();
            // 使用CAS确保线程安全
            if (INSTANCE.compareAndSet(null, singleton)) {
                return singleton;
            }
        }
    }

}
  • 单例模式的最佳实践——枚举式单例(线程安全)
class  EnumSingleton {
    private EnumSingleton() {}

    public static EnumSingleton getInstance() {
        return SingletonEnum.SINGLETON.getInstance();
    }

    public enum SingletonEnum {
        SINGLETON;
        private EnumSingleton instance;

        SingletonEnum() {
            instance = new EnumSingleton();
        }

        public EnumSingleton getInstance() {
            return instance;
        }
    }
}
说明:Java做了对枚举类做了特殊的规定:在序列化时Java仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过java.lang.Enum的valueOf()方法来根据名字查找枚举对象;另外不能使用newInstance()反射创建枚举类实例。因此,利用枚举的特性来解决线程安全和单一实例的问题,还可以有效防止反射和反序列化对单例的破坏
weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
python017基于Python贫困生资助管理系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值