设计模式之单例模式

单例模式

定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点

引子:读取配置文件

很多地方要用到,如果每次都new 一个对象的话,会浪费内存资源。

image.png

改装成饿汉式(饿汉式有线程并发问题,懒汉式没有)

image.png
也可以完成需求,但是节约资源了?因为只有一个地方去使用,也见不到效果

场景:需要读取配置,这个用途在开发中是很常见的。

package com.tao.YanMoDesignPattern.singleton.pattern.case1_Origin;import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;/*** @Author Mi_Tao* @Date 2023/7/23* @Description* @Version 1.0**/
public class AppConfig {private String parameterA;private String parameterB;public AppConfig(){readConfig();}private void readConfig() {Properties properties = new Properties();InputStream in = null;try {in = AppConfig.class.getResourceAsStream("/Appconfig.properties");properties.load(in);// 把配置文件中的内容读出来设置到属性上this.parameterA = properties.getProperty("parameterA");this.parameterB = properties.getProperty("parameterB");} catch (IOException e) {System.out.println("转载配置文件出错了!");e.printStackTrace();}finally {try {in.close();} catch (IOException e) {e.printStackTrace();}}}public String getParameterA() {return parameterA;}public String getParameterB() {return parameterB;}
}

配置类位置

在这里插入图片描述
直接的做法,读取文件

package com.tao.YanMoDesignPattern.singleton.pattern.case1_Origin;/*** @Author Mi_Tao* @Date 2023/7/23* @Description* @Version 1.0**/
public class Client {public static void main(String[] args) {// 创建读取应用的配置对象AppConfig config = new AppConfig();String parameterA = config.getParameterA();System.out.println("parameterA = " + parameterA);String parameterB = config.getParameterB();System.out.println("parameterB = " + parameterB);}
}

这种方式:快捷。但是如果但很多的类都需要使用到这些配置,就会大量new 出重复的对象,造成资源浪费!!

解决方法:既然这些配置都是一样的,我们其实只需要一个实例就行。所以我们可以使用单例模式
而常见单例的方法也是多样的:

1、饿汉式

package com.tao.YanMoDesignPattern.singleton.pattern.case1_Origin;/*** 饿汉式** @Author Mi_Tao* @Date 2023/7/23* @Description* @Version 1.0**/
public class HungrySingleton {//定义一个变量来存储创建好的类实例,只能创建一次private static HungrySingleton uniqueInstance = new HungrySingleton();/*** 构造私有化方法,可以再内部控制创建实例的数目*/private static HungrySingleton getInstance() {// 直接使用创建好的实例return uniqueInstance;}/*** 单例可以有自己的操作*/public void singletonOperation(){}public String getSingletonData() {return singletonData;}// 属性,单例可以有自己的属性private String singletonData;}

2、懒汉式

package com.tao.YanMoDesignPattern.singleton.pattern.case1_Origin;/*** 懒汉式** @Author Mi_Tao* @Date 2023/7/23* @Description* @Version 1.0**/
public class LazySingleton {//定义一个变量来存储创建好的类实例private static LazySingleton uniqueInstance = null;/*** 构造私有化方法,可以再内部控制创建实例的数目*/private LazySingleton() {}/*** 获取单例** @return {@link LazySingleton}*/public static synchronized LazySingleton getSingleton(){// 判断存储实例的变量是否有值if (uniqueInstance == null){// 如果没有,就创建一个uniqueInstance = new LazySingleton();}// 否则直接返回return uniqueInstance;}/*** 单例可以有自己的操作*/public void singletonOperation(){}public String getSingletonData() {return singletonData;}// 属性,单例可以有自己的属性private String singletonData;}

测试

package com.tao.YanMoDesignPattern.singleton.pattern.case1_Origin;/*** @Author Mi_Tao* @Date 2023/7/23* @Description* @Version 1.0**/
public class ClientV2_Hungry {public static void main(String[] args) {// 创建读取应用的配置对象AppConfigV2_Hungry config = AppConfigV2_Hungry.getInstance();String parameterA = config.getParameterA();System.out.println("parameterA = " + parameterA);String parameterB = config.getParameterB();System.out.println("parameterB = " + parameterB);}
}

懒汉式。从名字不难理解。在需要使用的使用才会去创建,而不去创建就不去创建。但是会有并发问题。
并发问题的解决,我们可以使用双检锁来升级一下,解决问题

package com.tao.YanMoDesignPattern.singleton.pattern.case1_Origin;/*** 懒汉式** @Author Mi_Tao* @Date 2023/7/23* @Description 考虑并发时候的单例 双检锁* @Version 1.0**/
public class LazySingleton_current {//定义一个变量来存储创建好的类实例  内存屏障去掉,直接访问共享内存private volatile static LazySingleton_current uniqueInstance = null;/*** 构造私有化方法,可以再内部控制创建实例的数目*/private LazySingleton_current() {}/*** 获取单例** @return {@link LazySingleton_current}*/public static synchronized LazySingleton_current getSingleton(){// 判断存储实例的变量是否有值if (uniqueInstance == null){synchronized (LazySingleton_current.class){if (uniqueInstance == null){// 如果没有,就创建一个uniqueInstance = new LazySingleton_current();}}}// 否则直接返回return uniqueInstance;}/*** 单例可以有自己的操作*/public void singletonOperation(){}public String getSingletonData() {return singletonData;}// 属性,单例可以有自己的属性private String singletonData;}

tips
使用枚举类也可以实现单例

本文参考:《研磨设计模式》
相关代码: https://gitee.com/zitaoyang/design-mode

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

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

相关文章

【计算机网络】11、网桥(bridge)、集线器(hub)、交换机(switch)、路由器(router)、网关(gateway)

文章目录 一、网桥(bridge)二、集线器(hub)三、交换机(switch)四、路由器(router)五、网关(gateway) 对于hub,一个包过来后,直接将包转发到其他口。 对于桥&…

【Linux命令200例】cp用于复制文件和目录(常用)

🏆作者简介,黑夜开发者,全栈领域新星创作者✌,阿里云社区专家博主,2023年6月csdn上海赛道top4。 🏆本文已收录于专栏:Linux命令大全。 🏆本专栏我们会通过具体的系统的命令讲解加上鲜…

SpringBoot项目增加logback日志文件

一、简介 在开发和调试过程中,日志是一项非常重要的工具。它不仅可以帮助我们快速定位和解决问题,还可以记录和监控系统的运行状态。Spring Boot默认提供了一套简单易用且功能强大的日志框架logback,本文将介绍如何在Spring Boot项目中配置和…

Python web实战之 Django 的 ORM 框架详解

本文关键词:Python、Django、ORM。 概要 在 Python Web 开发中,ORM(Object-Relational Mapping,对象关系映射)是一个非常重要的概念。ORM 框架可以让我们不用编写 SQL 语句,就能够使用对象的方式来操作数据…

8.3 作业 c高级

1.递归实现&#xff0c;输入一个数&#xff0c;输出这个数的每一位&#xff1a; #include<myhead.h>void print_digit(int num) {if(num<10){printf("%d",num);puts("");}else{print_digit(num/10); //递归打印除最后一位外的数printf("%…

【数据结构】二叉树、二叉搜索树、平衡二叉树、红黑树、B树、B+树

概述 二叉树&#xff08;Binary Tree&#xff09;&#xff1a;每个节点最多有两个子节点&#xff08;左子节点和右子节点&#xff09;&#xff0c;没有限制节点的顺序。特点是简单直观&#xff0c;易于实现&#xff0c;但查找效率较低。 二叉搜索树&#xff08;Binary Search…

华为数通HCIP-PIM原理与配置

组播网络概念 组播网络由组播源&#xff0c;组播组成员与组播路由器组成。 组播源的主要作用是发送组播数据。 组播组成员的主要作用是接收组播数据&#xff0c;因此需要通过IGMP让组播网络感知组成员位置与加组信息。 组播路由器的主要作用是将数据从组播源发送到组播组成员。…

Flutter 添加 example流程

一、已有Flutter工程&#xff08;命令&#xff09;添加 example 1、cd 工程(flutter_plugin ,是自己创建的)根目录 例: flutter create example 执行命令创建example PS&#xff1a;cd example 后执行flutter doctor 后就可以看到效果 2、如果需要指定iOS/Android 语言,请添加…

Qt应用开发(基础篇)——数值微调输入框QAbstractSpinBox、QSpinBox、QDoubleSpinBox

目录 一、前言 二、QAbstractSpinBox类 1、accelerated 2、acceptableInput 3、alignment 4、buttonSymbols 5、correctionMode 6、frame 7、keyboardTracking 8、readOnly 9、showGroupSeparator 10、specialValueText 11、text 12、wrapping 13、信号 二、Q…

微信小程序 - 解析富文本插件版们

一、html2wxml 插件版 https://gitee.com/qwqoffice/html2wxml 申请使用注意事项 插件版本解析服务是由 QwqOffice 完成&#xff0c;存在不稳定因素&#xff0c;如对稳定性有很高的要求&#xff0c;请自行搭建解析服务&#xff0c;或在自家服务器上直接完成解析。对于有关插…

【Linux】 UDP网络套接字编程

&#x1f34e;作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;Linux系统网络编程 文章目录 一、网络通信的本质&#xff08;port标识的进程间通信&#xff09;二、传输层协议UDP/TCP认识传输层协议UDP/TCP网络字节序问题&#xff08;规定大端&#xff09; 三、socket编…

VGG卷积神经网络-笔记

VGG卷积神经网络-笔记 VGG是当前最流行的CNN模型之一&#xff0c; 2014年由Simonyan和Zisserman提出&#xff0c; 其命名来源于论文作者所在的实验室Visual Geometry Group。 测试结果为&#xff1a; 通过运行结果可以发现&#xff0c;在眼疾筛查数据集iChallenge-PM上使用VGG…

Prometheus中的关键设计

1、标准先行&#xff0c;注重生态 Prometheus 最重要的规范就是指标命名方式&#xff0c;数据格式简单易读。比如&#xff0c;对于应用层面的监控&#xff0c;可以要求必须具备这几个信息。 指标名称 metric Prometheus 内置建立的规范就是叫 metric&#xff08;即 __name__…

C++ 用指针处理数组元素

指针加减运算的特点使得指针特别合适于处理存储在一段连续内存空间中的同类数据。而数组恰好是具有一定顺序关系的若干同类型变量的集合体&#xff0c;数组元素的存储在物理上也是连续的&#xff0c;数组名就是数组存储的首地址。这样&#xff0c;便可以使用指针来对数组及其元…

使用docker 搭建nginx + tomcat 集群

创建3个Tomcat容器&#xff0c;端口分别映射到 8080,8081,8082&#xff0c;使用数据卷挂载&#xff0c;分别将宿主机目录下的 /opt/module/docker/tomcat3/ROOT1/&#xff0c;/opt/module/docker/tomcat3/ROOT2/&#xff0c;/opt/module/docker/tomcat3/ROOT2/ 挂载到 容器内部…

Gitignore忽略文件

默认情况下&#xff0c;Git会监视我们项目中的所有内容&#xff0c;但是有些内容比如mode_modules中的内容&#xff0c;我们不希望他被Git所管理。 我们可以在我们项目目录中添加一个 .gitignore 文件来设置那些需要git忽略的文件。

rest-apiV2.0.0升级为simplest-api开源框架生态之simplest-jpa发布

什么是 simplest simplest 追求存粹简单和极致。 旨在为项目快速开发提供一系列的基础能力&#xff0c;方便用户根据项目需求快速进行功能拓展 不在去关心一些繁琐。重复工作&#xff0c;而是把重点聚焦到业务。 前言 程序 10 年。作为一个多年程序。深知每个项目和程序&a…

通用商城项目(中)

金山编译器出问题了。下面段落标号全出问题了&#xff0c;排版也出问题了。懒得改了。 使用对象存储OSS&#xff0c;保存品牌logo 新建Module&#xff0c;提供上传、显示服务 有些不明所以的&#xff0c;按照steinliving-commodity配置了一通pom.xml 新建application.yml&…

实现邮箱管理之gmail邮箱、office365(Azure)邮箱之披荆斩棘问题一览

要进行Office365邮箱的授权对接&#xff0c;你需要先申请一个应用&#xff0c;并获取授权访问令牌。 以下是一个简单的步骤&#xff1a; 登录 Azure 门户&#xff1a;https://portal.azure.com/创建一个新的应用程序&#xff0c;或者使用现有的应用程序。要创建新的应用程序&…

从0到1开发go-tcp框架【3-读写协程分离、引入消息队列、进入连接管理器、引入连接属性】【基础篇完结】

从0到1开发go-tcp框架【3-读写协程分离、引入消息队列、进入连接管理器、引入连接属性】 1 读写协程分离[v0.7] 添加一个Reader和Writer之间通信的channel添加一个Writer goroutineReader由之前直接发送给客户端改为发送给通信channel启动Reader和Writer一起工作 zinx/znet/co…