设计模式-单例模式实战

目录

  • 一、引言
  • 二、适用场景
  • 三、代码实战
    • 饿汉式单例模式
    • 懒汉式单例模式
    • 双重检查锁定单例模式
    • 静态内部类单例模式
  • 四、实际应用举例
      • Runtime解析
  • 五、结论

一、引言

    单例模式是一种创建型设计模式,用于确保一个类只有一个实例,且提供全局访问点以访问该实例。以下是单例模式的关键特点:

  • 私有构造函数:单例类通常会将其构造函数声明为私有,以防止外部直接创建实例。
  • 私有静态实例:单例类通常会维护一个私有的静态实例变量,用于保存唯一的实例。
  • 静态获取方法:单例类通常提供一个静态的获取方法,允许客户端代码访问单例实例。
  • 惰性初始化:单例实例通常是在首次访问时初始化的,以延迟实例化,提高性能。
  • 线程安全:单例模式通常需要考虑线程安全性,以防止多个线程同时创建实例。

二、适用场景

    单例模式适用于以下情况:

  1. 全局资源访问:当一个对象需要在系统中全局唯一访问时,如配置管理、日志记录、数据库连接等。
  2. 控制资源访问:当需要限制某种资源(如线程池、连接池、缓存)的访问数量时。
  3. 惰性初始化:当对象的创建和初始化可能具有较高的开销,但只在需要时才进行时。
  4. 线程池:用于创建线程池,以便在整个应用程序中维护一个可管理的线程池实例。

三、代码实战

饿汉式单例模式

public class EagerSingleton {private static final EagerSingleton instance = new EagerSingleton();private EagerSingleton() {// 私有构造函数}public static EagerSingleton getInstance() {return instance;}
}

原理:在类加载时,即实例化前,实例变量就已经被分配内存,因此保证了线程安全。但可能会浪费内存,因为不一定会使用该实例。

懒汉式单例模式

public class LazySingleton {private static LazySingleton instance;private LazySingleton() {// 私有构造函数}public static synchronized LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}
}

原理:该实现使用惰性初始化,只有在第一次调用 getInstance() 时才创建实例。通过加锁来确保线程安全,但可能引发性能问题。

双重检查锁定单例模式

public class DoubleCheckedSingleton {private volatile static DoubleCheckedSingleton instance;private DoubleCheckedSingleton() {// 私有构造函数}public static DoubleCheckedSingleton getInstance() {if (instance == null) {synchronized (DoubleCheckedSingleton.class) {if (instance == null) {instance = new DoubleCheckedSingleton();}}}return instance;}
}

原理:通过双重检查,确保只在第一次创建实例时使用同步锁,提高了性能。

静态内部类单例模式

public class InnerStaticSingleton {private InnerStaticSingleton() {// 私有构造函数}private static class SingletonHolder {private static final InnerStaticSingleton instance = new InnerStaticSingleton();}public static InnerStaticSingleton getInstance() {return SingletonHolder.instance;}
}

原理:利用Java类加载机制,保证只有在首次访问 getInstance() 时才加载内部类并创建实例。

四、实际应用举例

Java开发工具包(JDK)中有一些类和模块使用了单例模式来管理资源或确保全局唯一性。以下是一些示例:

  1. Runtime类:java.lang.Runtime类是Java的运行时系统入口,它使用了饿汉式单例模式来确保在应用程序中只有一个运行时实例。你可以通过Runtime.getRuntime()方法获取运行时对象的唯一实例,从而执行与运行时环境相关的操作。
  2. Calendar类:java.util.Calendar类是用于日期和时间操作的抽象类,它提供了一个getInstance()方法,返回特定日历系统的单例实例。这是一个懒汉式单例模式的示例,以确保只有一个日历实例。
  3. Desktop类:java.awt.Desktop类用于与桌面操作系统进行交互,如打开文件、浏览网页等。它使用了饿汉式单例模式来保证只有一个桌面对象的实例。

这些示例中的单例模式确保了全局唯一性,并用于管理特定资源或提供全局访问点。虽然不是所有JDK中的类都使用单例模式,但一些核心类确实使用了这种设计模式来确保一些特定的实例只存在一个。

Runtime解析

在 Java 的 Runtime 类中,使用了饿汉式单例模式来确保在应用程序中只有一个运行时实例。以下是 Runtime 类的部分代码,展示了如何使用单例模式来创建和返回运行时实例:

public class Runtime {private static Runtime currentRuntime = new Runtime();// 私有构造函数,防止外部实例化private Runtime() {}// 获取当前运行时实例public static Runtime getRuntime() {return currentRuntime;}// ...其他方法和功能...
}

解释:

  1. currentRuntime 是一个静态私有成员变量,它在类加载时被初始化。这就是饿汉式单例模式的特点,实例在类加载时就被创建,而不是在首次访问时才创建。
  2. 构造函数 private Runtime() 被声明为私有,这意味着外部代码无法直接实例化 Runtime 类。
  3. getRuntime() 方法是一个静态方法,用于获取当前运行时实例。它返回的是 currentRuntime 静态实例变量,确保每次调用 getRuntime() 方法都返回同一个实例。

这种设计确保了在整个应用程序中只有一个运行时实例,因为 currentRuntime 在类加载时就被创建,并且构造函数是私有的,外部代码无法创建新的实例。这是一种有效的方式,以确保只有一个全局运行时环境,以便执行与运行时环境相关的操作,如执行外部进程、获取系统信息等。

五、结论

以下是单例模式的一些总结和结论:
优点:

  1. 全局唯一性:单例模式确保一个类只有一个实例,因此能够全局唯一地管理特定类型的资源或状态。
  2. 惰性初始化:单例实例通常是在首次访问时初始化的,从而避免了不必要的资源浪费。
  3. 全局访问点:单例提供了一个全局访问点,允许应用程序中的其他对象轻松访问单例实例。
  4. 线程安全性:合理实现的单例模式可以确保多线程环境下的线程安全性,防止多次实例化。

缺点和注意事项:

  1. 过度使用:过度使用单例模式可能导致全局状态的滥用,使代码难以维护和测试。应谨慎使用。
  2. 不适用于所有情况:并非所有类都适合作为单例,有些类需要多个实例来独立处理不同任务。
  3. 测试困难:单例模式的全局状态共享可能会使单元测试变得复杂,因此需要额外的努力来测试应用。
  4. 多例模式:在某些情况下,可能需要多个实例,而不仅仅是一个全局唯一实例。

总的来说,单例模式是一种非常有用的设计模式,用于确保一个类只有一个实例。它在管理全局资源、限制实例数量以及提供全局访问点等方面发挥了重要作用。然而,在使用单例模式时,应慎重考虑,确保它真正符合应用程序的需求。此外,要注意线程安全性和测试问题,以确保单例实现的正确性。

点赞收藏,富婆包养✋✋

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/158594.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

「Verilog学习笔记」根据状态转移表实现时序电路

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点,刷题网站用的是牛客网 分析 可得逻辑表达式为 可得逻辑表达式为 timescale 1ns/1nsmodule seq_circuit(input A ,input clk ,input rst_n,outpu…

阿里云高校计划学生和教师完成认证领取优惠权益

阿里云高校计划学生和教师均可参与,完成学生认证和教师验证后学生可以免费领取300元无门槛代金券和3折优惠折扣,适用于云服务器等全量公共云产品,订单原价金额封顶5000元/年,阿里云百科aliyunbaike.com分享阿里云高校计划入口及学…

error: ‘ui/ui_uimainwindow.h‘ file not found

问题:在刚好创建的Qt Designer Form Class类中,发现类的.cpp文件中有ui头文件未找到 原因:.ui文件没有被识别到,或者.ui文件不存在,导致ui头文件未创建而报错。 解决:若修改了.ui文件,随手ctrls…

python网络通信之基础知识填坑

文章目录 版权声明网络通信要素IP地址ifconfig和ping命令ifconfig (Interface Configuration)ping 端口和端口号的介绍端口号的分类socket介绍TCPTCP简介TCP的特点 UDPUDP简介UDP特点 版权声明 本博客的内容基于我个人学习黑马程序员课程的学习笔记整理而成。我特此声明&#…

npm install安装报错

npm WARN notsup Not compatible with your version of node/npm: v-click-outside-x3.7.1 npm ERR! Error while executing: npm ERR! /usr/bin/git ls-remote -h -t ssh://gitgithub.com/itargaryen/simple-hotkeys.git 解决办法1:(没有解决我的问题…

Metis安装(5.0.1与4.0.3)

文章目录 [TOC](文章目录) Metis安装的主要步骤一、选择指定编译器二、指定安装路径三、安装 Metis安装的主要步骤 务必下载指定版本的metis源码,然后进行解压,进入源码的主目录下,在安装之前,通常会要求linux系统上安装了GCC&am…

2023.11.22使用flask做一个简单的图片浏览器

2023.11.22使用flask做一个简单的图片浏览器 功能: 实现图片浏览(翻页)功能 程序页面: 程序架构: 注意:在flask中常会使用src=“{{ url_for(‘static’, filename=‘images/’ + image) }}”,这段代码是在Flask框架中用于获取静态文件的URL的。在Flask中,静态文件…

CSS实现三角形

CSS实现三角形 前言第一种:bordertransparent第二种borderrgb使用unicode字符 前言 本文讲解三种实现三角形的方式,并且配有图文以及代码解说。那么好,本文正式开始。 第一种:bordertransparent border是边框,而transparent是透明的颜色&a…

【HarmonyOS】获取备案需要的公钥和MD5签名问题

【关键字】 HarmonyOS、公钥、MD5签名 【问题描述】 有cp反馈Harmony App如何获取备案需要的公钥和MD5签名。 【解决方案】 1、获取备案需要的公钥: 1)用记事本打开签名对应.cer文件 2)里面的内容粘贴到一个可以查看证书的网站上面&…

json_to_mask报错imgviz安装

直接安装超时,解决办法: pip install -i https://pypi.tuna.tsinghua.edu.cn/simple imgviz1.2.0

maven pom引入依赖不报红,但是项目Dependencies中没有引入jar包

前言 小编我将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识,有兴趣的小伙伴可以关注一下! 也许一个人独行,可以走的很快,但是一群人结伴而行,才能走的更远!让我们在成长的道路上互相学习&…

OCR是什么意思,有哪些好用的OCR识别软件?

1. 什么是OCR? OCR(Optical Character Recognition)是一种光学字符识别技术,它可以将印刷体文字转换为可编辑的电子文本。OCR技术通过扫描和分析图像中的文字,并将其转化为计算机可识别的文本格式,从而…

mysql开启慢查询日志

直接看原文: 原文链接:MySQL慢查询日志开启、配置、分析等操作_Code0cean的博客-CSDN博客 ------------------------------------------------------------------------------------------------------------------------------- 命令总结: 查看慢查询日志文件 tail -100f …

【Unity3D】自动构建Android包时指定aab或apk以及设置sdk版本

EditorUserBuildSettings.buildAppBundle true; 为true打出Android App bunle文件(.aab) 默认为false打出apk文件 PlayerSettings.Android.targetSdkVersion (AndroidSdkVersions)33; 设置指定目标SDK版本 PlayerSettings.Android.minSdkVersion AndroidSdkVersions.Andro…

linux - libreoffice使用

linux - libreoffice使用 在线安装 1.yum源安装 [roottest ~]# yum update [roottest ~]# yum install -y libreoffice-headless libreoffice-writer libreoffice-calc libreoffice-impress [roottest ~]# yum install -y libreoffice2.接下来就可以使用了 [roottest ~]# l…

微博头条文章开放接口报错 auth by Null spi

接口文档地址 https://open.weibo.com/wiki/Toutiao/api 接口说明 https://api.weibo.com/proxy/article/publish.json 请求方式 POST 请求参数 参数名称类型是否必需描述titlestring是文章标题,限定32个中英文字符以内contentstring是正文内容,限制9…

西米支付:游戏支付的概念,发展,什么是游戏支付接口?

游戏支付平台是指专门用于游戏交易的在线支付系统。它为玩家提供了方便快捷的支付服务,让他们能够在游戏中购买虚拟物品、充值游戏币等。 游戏支付平台通过安全的支付通道和多种支付方式,保障了交易的安全性和便捷性。 同时,它也为游戏开发…

精彩预告 | OpenHarmony即将亮相MTSC 2023

MTSC 2023 第12届中国互联网测试开发大会(深圳站)即将于2023年11月25日,在深圳登喜路国际大酒店举办,大会将以“1个主会场4个平行分会场”的形式呈现,聚集一众顶尖技术专家和行业领袖,围绕如今备受关注的行…

【Redis】渐进式遍历数据库管理

文章目录 渐进式遍历scan 数据库管理切换数据库清除数据库 获取当前数据库key的个数 渐进式遍历 Redis使⽤scan命令进⾏渐进式遍历键,进⽽解决直接使⽤keys获取键时能出现的阻塞问题。每次scan命令的时间复杂度是O(1),但是要完整地完成所有键的遍历&…

Android手机如何用Charles抓包HTTPS接口

对Charles的安装和使用,这里就不重复介绍了,之前有介绍Charles工具。 本文重点介绍在Android手机上如何配置抓包环境 1.获取Charles配置 去Help -> SSL Proxying -> Install Charles Root Certificate on a Mobile Device or Remote Browser 查…