设计模式之单例设计模式

这篇具有很好参考价值的文章主要介绍了设计模式之单例设计模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、单例设计模式

就是一个类只允许创建一个对象,那么我们称该类为单例类,这种设计模式我们称为单例模式。

二、为什么使用单例模式

资源共享:有些类拥有共享的资源,例如数据库连接池、线程池、缓存等。使用单例模式确保只有一个实例,避免资源浪费和竞争条件。

线程安全:单例模式可以用来保证多线程环境下只有一个实例,从而避免竞争条件和不一致性。

避免全局变量:使用单例模式可以减少全局变量的数量,从而降低了不同部分之间的耦合。这有助于使代码更加可维护和可测试。

全局访问点:单例模式提供了一个全局的访问点,使得其他对象可以轻松地获取该实例,而无需创建多个实例或传递实例引用。这对于配置管理、日志记录、事件管理等非常有用。

三、如何实现单例

常见的单例设计模式有以下五种:

1、饿汉式

2、懒汉式

3、双重检查锁

4、静态内部类

5、枚举

我们在编写以上五种单例代码的时候需要注意以下几点:

1、构造器私有化

2、暴露一个公共方法获取单例对象

3、是否考虑线程安全

4、是否考虑加载时间

对于1、2两点来说,我常常是这样想的,一个单例类要有两个private、两个static。构造器和对象必须用private修饰,对象和获取对象的方法必须用static修饰。

注:1、将对象定义为static的主要原因有两个,其一是确保只有一个实例可以被全局访问。static成员变量是属于类而不是实例的,这意味着不管创建多少个类的实例,它们都共享相同的static成员变量。这对于单例模式非常重要,因为单例的核心目标是确保只有一个实例存在。其二是返回对象的方法是静态的,静态方法不能访问非静态成员变量。

我们先来看第一个单例模式的代码

四、饿汉式

饿汉式的实现方式比较简单。具体的代码实现如下:

public class EagerSingleton {

    private final static EagerSingleton instance = new EagerSingleton();

    private EagerSingleton() {}

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

从上述代码可以看出,在类加载的时候,instance 静态实例就已经创建并初始化好了,所以,instance 实例的创建过程是线程安全的。如果不需要延迟加载,并且确保在多线程环境下只有一个实例存在,饿汉式单例是一种有效的选择。

五、懒汉式

有饿汉式,对应地,就有懒汉式。懒汉式相对于饿汉式的优势是支持延迟加载,具体的代码实现如下:

public class LazySingleton {

    private static LazySingleton instance;

    private LazySingleton() {}

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

以上的写法本质上是有问题,在多线程环境下,其实是无法保证其单例的特点的,很有可能会有超过一个线程同时执行了new Singleton();解决的办法简单粗暴,直接加锁,代码如下:

public class LazySingleton {

    private static LazySingleton instance;

    private LazySingleton() {}

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

以上的写法确实可以保证jvm中有且仅有一个单例实例存在,但是方法上加锁会极大 的降低获取单例对象的并发度。同一时间只有一个线程可以获取单例对象,为了解决 以上的方案则有了第三种写法。

六、双重检查锁

饿汉式不支持延迟加载,懒汉式有性能问题,不支持高并发。那我们再来看一种既支 持延迟加载、又支持高并发的单例实现方式,也就是双重检测实现方式(办法总比困难多嘛):在这种实现方式中,只要 instance 被创建之后,即便再调用 getInstance() 函数也不会再进入到加锁逻辑中了。所以,这种实现方式解决了懒汉式并发度低的问题。具体的代码实现如下:

public class DoubleCheckSingleton {

    private volatile static DoubleCheckSingleton instance;

    private DoubleCheckSingleton() {}

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

volatile: 加volatile关键字是为了保证顺序性,因为在Java中创建对象通常需要三个主要步骤,分别为分配内存空间、初始化对象、引用赋值,正是因为创建需要这三步,导致在多线程环境下,出现某些线程拿到的对象是半初始化对象。譬如:

线程1进入双重检测锁,执行第一次检测,发现共享的实例变量为null,因此进入同步块。

线程1在同步块内部创建了单例对象,然后将实例变量指向新创建的对象。

由于指令重排序,创建对象的操作被移到了实例变量赋值之前。这样,实例变量被赋值,但对象可能还没有完全初始化。

线程2在第一次检测时,发现实例变量不为null,然后直接返回实例,但实例可能没有完全初始化,导致不完整或不正确的对象。

七、静态内部类

我们再来看一种比双重检测更加简单的实现方法,那就是利用 Java 的静态内部类。 它有点类似饿汉式,但又能做到了延迟加载。具体是怎么做到的呢?我们先来看它的代码实现如下:

public class InnerSingleton {

    private InnerSingleton(){}

    public static InnerSingleton getInstance(){
        return InnerSingletonHolder.instance;
    }
    // 静态内部类实例化外部类对象
    private static class InnerSingletonHolder{
        private final static InnerSingleton instance = new InnerSingleton();
    }
}

InnerSingletonHolder 是一个静态内部类,当外部类 InnerSingleton被加载的时候,并不会创建 InnerSingletonHolder 实例对象。只有当调用 getInstance() 方法时,

InnerSingletonHolder 才会被加载,这个时候才会创建 instance。insance 的唯一性、创建过程的线程安全性,都由 JVM 来保证。所以,这种实现方法既保证了线程安全,又能做到延迟加载。

八、枚举

基于枚举类型的单例实现。这种实现方式通过 Java 枚举类型本身的特性,保证了实例创建的线程安全性和实例的唯一性。具体的代码如下:

public enum EnumSingleton {
    // 对应的枚举类,任何一个枚举项都是一个天然的单例
    // 本质上就是static final EnumSingleton instance = new EnumSingleton()
    // 枚举本身支持懒加载
    INSTANCE;
}

更通用的写法如下:

public class EnumSingleton {
    private EnumSingleton(){}

    public static enum SinglentonEnum{
        ESingleton;
        private EnumSingleton instance = null;
        private SinglentonEnum(){
            instance = new EnumSingleton();
        }
        public EnumSingleton getInstance(){
            return instance;
        }
    }
}

通过调用 EnumSingleton.SinglentonEnum.ESingleton.getInstance() 方法可以获取单例对象。

单例模式就分享到这,希望可以帮助各位码友!点个赞吧!!!

文章来源地址https://www.toymoban.com/news/detail-724163.html

到了这里,关于设计模式之单例设计模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C#设计模式之单例模式

    单例模式(Singleton)保证一个类仅有一个实例,并提供一个访问它的全局访问点。 单例模式的结构图如下所示: 对一些类来说,只有一个实例是很重要的。如何才能保证一个类只有一个实例并且这个实例易于被访问呢? 基于程序员之间的约定或是利用全局变量吗? 虽然这样

    2024年02月03日
    浏览(36)
  • Unity设计模式之单例模式

    单例模式(Singleton)是设计模式中很常见的一种设计模式,目的是为了让一个类在程序运行期间有且仅有一个实例,且方便全局访问。 1、私有的构造函数。 2、含有一个该类的静态私有对象。 3、静态的公有函数或属性,方便用户创建或者获取它本身的静态私有对象。 当项目

    2023年04月09日
    浏览(39)
  • c++设计模式之单例模式

    一个类无论创建多少对象 , 都只能得到一个实例 如上述代码中,我们通过new运算符创建出了类A的三个对象实例,而我们现在要做的是,如何设计类A,使得上述代码运行之后永远只产生同一个对象实例         我们知道,一个类对象是通过这个类的构造函数创建的,因此

    2024年01月19日
    浏览(39)
  • C#--设计模式之单例模式

    单例模式大概是所有设计模式中最简单的一种,如果在面试时被问及熟悉哪些设计模式,你可能第一个答的就是单例模式。 单例模式的实现分为两种: 饿汉式:在静态构造函数执行时就立即实例化。 懒汉式:在程序执行过程中第一次需要时再实例化。 两者有各自适用的场景

    2024年02月14日
    浏览(32)
  • 万字解析设计模式之单例模式

    单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个 单一 的类,该类负责创建自己的对象,同时确保 只有单个对象被创建 。这个类提供了一种访问其唯一的对象的方式,

    2024年02月08日
    浏览(28)
  • 深入理解设计模式-创建型之单例模式

    如果有些数据在系统中应该且只能保存一份,那就应该设计为单例类。 如:配置类:在系统中,我们只有一个配置文件,当配置文件被加载到内存之后,应该被映射为一个唯一的【配置实例】,此时就可以使用单例,当然也可以不用。 全局计数器:我们使用一个全局的计数

    2024年02月12日
    浏览(27)
  • 跟着GPT学设计模式之单例模式

    单例设计模式(Singleton Design Pattern)一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。 单例有几种经典的实现方式,它们分别是:饿汉式、懒汉式、双重检测、静态内部类、枚举。 处理资源访问冲突,

    2024年02月05日
    浏览(30)
  • C++设计模式创建型之单例模式

    一、概述         单例模式也称单态模式,是一种创建型模式,用于创建只能产生一个对象实例的类。例如,项目中只存在一个声音管理系统、一个配置系统、一个文件管理系统、一个日志系统等,甚至如果吧整个Windows操作系统看成一个项目,那么其中只存在一个任务管理

    2024年02月14日
    浏览(30)
  • 【Java 设计模式】创建型之单例模式

    在软件开发中,单例模式是一种常见的设计模式, 它确保一个类只有一个实例,并提供一个全局访问点 。单例模式在需要控制某些资源,如数据库连接池、线程池等共享资源的情况下非常有用。在本文中,我们将介绍 Java 设计模式中的单例模式,了解其实现方式、使用场景

    2024年01月18日
    浏览(30)
  • Gof23设计模式之单例模式(完整)

    单例模式(Singleton pattern)是Java中最简单的设计模式之一。这种设计模式属于创建型模型,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访

    2024年02月10日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包