我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java设计模式之单例模式

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java设计模式之单例模式

什么是设计模式?

百科:

设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。

设计模式是软件行业的通用的设计标准,在Java同样通用,主要有23种设计模式如下:

在这里插入图片描述

有的小伙伴可能会问,这么多,学得完吗?

答:不好意思,不要太自信了,一般人还真学不完,不过一些常用的设计模式,例如上图中标红的单例模式、工厂模式、代理模式等设计模式,还是需要花些时间和精力去多多了解一下,相信会对自己在程序设计或写代码时有很大的帮助。

本文主要来聊一聊设计模式中创建型的单例模式,进入正文~

单例模式是什么?

学习Java的小伙伴,相信都写过Class类吧,创建某个类实例化对象的核心是new MyClass()来实现,如果没有任何设计规范,在日常开发写代码时,如果实例被用的地方很多,每次调用的时候都通过new MyClass()得到实例化对象,代码重复而且频繁的创建对象还影响性能,而有些场景我们只需要提供该类的一个实例即可,例如平时比较常见的线程池、日志对象、缓存等,一般只需要确保有一个实例即可,这种确保某个类只有一个实例并且能够类自身提供自动创建实例化对象的设计模式即称为单例模式。

单例模式设计的原则是什么?

  • 构造方法私有化:既然是单例,就不能将类的构造函数暴露在外面,因此需要重写构造函数为私有化;
  • 要考虑线程安全:多线程环境下,要确保不会构造出多个实例对象。

Java实现单例模式的5种方式?

关于Java实现单例模式的有几种方式,网上有很多说法,有5种、6种甚至7种实现方式,本文出于单例模式设计的两个主要原则构造方法私有化和要考虑线程安全,不考虑线程安全的其他实现方式没有任何意义,主要有5种实现方式:

在这里插入图片描述

懒汉

使用懒汉式写法,主要是通过synchronized修饰实例化方法getInstance,保证了线程安全,并且只有调用getInstance时才初始化,顾此得名懒汉。

懒汉写法1:



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

懒汉写法2:

该写法等价于写法1,原因在于关键字synchronized的灵活运用,放在方法上修饰,加锁的对象是Singleton,等效于将synchronized移到方法内部作为一个同步块,并通过括号中的Singleton.class显示指定锁对象,效果是一样的。



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

饿汉

饿汉写法,只需要定义一个static静态变量instance = new Singleton(),简单的理解为在类加载时,也会完成单例对象的实例化工作。



public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return instance;
    }
}

细心的小伙伴会发现该过程并没有使用到synchronized关键字,那会不会线程不安全呢?答案是,不会,如果你大概了解过Java虚拟机即JVM(Java Virtual Machine),那你可能知道类加载过程为:加载 -> 验证 ->解析 ->初始化,而初始化阶段是执行类构造器<clinit>()方法的过程,<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块中的语句合成产生的。

《深入理解Java虚拟机》类加载机制章节部分说明:

虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确地加锁、同步,如果多个线程同时如初始化一个类,那么只会有一个线程去执行这个类的<clinit>()方法,其他线程都需要阻塞等待,知道活动线程执行<clinit>()方法完毕。

静态内部类

静态内部类这种方式,其实就是在类的内部创建一个static SingletonInner静态内部类,然后在静态内部类的内部再定义一个static final修饰的静态常量INSTANCE = new Singleton(),同样static修饰的SingletonInner静态内部类,会在JVM加载类时完成类的初始化并完成自己定义的静态常量单例实例化过程。



public class Singleton {
    private static class SingletonInner{
        private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton(){}
    public static Singleton getInstance(){
        return SingletonInner.INSTANCE;
    }
}

双重校验锁DCL(Double Check Lock)

DCL写法,其实与单例模式之懒汉写法2区别在于,synchronized同步块外面再套一层判断,并且使用了能确保线程安全核心volatile关键字修饰instance,表明单例变量是内存共享的,能够保证在多线程环境下的即时可见性。



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

枚举(num)

枚举方式很容易被大家给忽略掉了,但这种方式我觉得是最简单且又友好的一种推荐创建单例的方式,通过enum修饰Singleton单例类,仅需定义一个INSTANCE,然后在静态方法实例化方法getInstance中直接返回INSTANCE即可。



public enum Singleton {
    INSTANCE;
    public static Singleton getInstance(){
        return INSTANCE;
    }
}

总结

设计模式之单例模式,看似挺简单,其实还涉及了枚举enum、同步锁synchronized、JVM类加载机制、多线程volatile关键字的使用等Java的N个知识点。

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java设计模式之单例模式

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

java设计模式之单例模式解析

单例模式是最简单但同时也是很重要的一种设计模式,优点有以下几个方面:1.当内存占用特别大的类需要频繁地创建销毁时,单例模式可以节省内存和提高性能,例如myBatis里面的sessionFactory2.当需要对文件做单一读写时,例如同一时间
2023-05-31

Java设计模式-单例模式

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

python设计模式之单例模式

单例模式是一种创建型设计模式,它确保一个类有且只有一个特定类型的对象,并提供全局访问点。其意图为:确保类有且只有一个对象被创建为对象提供一个访问点,使程序可以全局访问该对象控制共享资源的并行访问简单理解:单例即为单个实例,也就是每次实例化创
2023-01-30

Android设计模式之单例模式

1、单例模式常见情景设计模式中,简单不过的是单例模式。先看看单例模式Singleton模式可以是很简单的,它的全部只需要一个类可以完成(看看这章可怜的UML图)。但是如果在“对象创建的次数以及何时被创建”这两点上较真
2022-06-06

JavaScript设计模式之单例模式

单例模式的定义是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2022-11-13

Java创建型设计模式之单例模式

Java单例模式是一种设计模式,它确保一个类只有一个实例,并提供一个全局访问点。可以使用多种方式实现单例模式,如饿汉式、懒汉式、双重检查锁定、静态内部类、枚举等,每种方式都有其优缺点,需要根据具体情况选择使用
2023-05-18

Android设计模式之单例模式实例

这篇文章主要介绍了Android设计模式之单例模式实例,单例模式是运用最广泛的设计模式之一,在应用这个模式时,单例模式的类必须保证只有一个实例存在
2023-05-16

java设计模式之怎么实现单例模式

这篇文章主要介绍了java设计模式之怎么实现单例模式的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇java设计模式之怎么实现单例模式文章都会有所收获,下面我们一起来看看吧。单元素的枚举类型经常成为实现 Sing
2023-07-04

Android设计模式之单例模式解析

在日常开发过程中时常需要用到设计模式,但是设计模式有23种,如何将这些设计模式了然于胸并且能在实际开发过程中应用得得心应手呢?和我一起跟着《Android源码设计模式解析与实战》一书边学边应用吧!今天我们要讲的是单例模式定义确保某一个类只有
2023-05-30

Android设计模式系列之单例模式

单例模式,可以说是GOF的23种设计模式中最简单的一个。 这个模式相对于其他几个模式比较独立,它只负责控制自己的实例化数量单一(而不是考虑为用户产生什么样的实例),很有意思,是一个感觉上很干净的模式,本人很喜欢这个模式。 android中
2022-06-06

Android设计模式之单例模式详解

单例模式一个类只有一个实例,并且可以全局访问使用应用场景如账户管理类,数据库操作类等(某个对象频繁被访问使用)常用方式饿汉式懒汉式同步加锁DCL双重加锁验证静态内部类枚举单例饿汉式加载类的同时立即进行初始化操作,对资源消耗很大public
2023-05-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录