设计模式之单例模式

设计模式C++实现(4)——单例模式 软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性:封装、继承、多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累。最近看设计模式的书,对于每个模式,用C++写了个小例子,加深一下理解。单例模式 阅读详情

单例模式几乎是所有模式中最简单的,用的也挺多,今天就讲讲单例模式

单例模式的定义:

保证一个类仅有一个实例(在内存中仅有该类一份字节码),并提供一个访问它的全局访问方法即可,.实例就是说运行期间才有的

使用场景:比如一个类中的方法在很多类中都要使用到,有静态和非静态的方法,非静态的方法必须使用对象才能调用,

那就意味着在运行期间就会new很多类在内存中,这样会导致内存吃紧,因此需要优化,优化就是减少内存的空间,而内存是存储对象的,所以减少对象的个数就是优化了内存,因此只需要在内存中保存一份这个类的对象即可,


既然在外部类中不能new这个对象,那么这个类的构造函数一定要私有,这个单例类只能在本类中创建了,那么它必须要对外提供访问到这个对象的方法,(也就是说单例类要对外提供方法访问到这个对象的实例)所以单例的2个条件就出来了

1:构造函数要私有化,也就是创建对象权限只能在本类中使用

2:提供方法让外界能够拿到单例类的对象实例


下面就按照上面分析的写一个单例的demo

<span style="font-size:24px;">package cn.handcool.singlton;
public class SingleTon {
	private SingleTon(){}
	public static SingleTon getInstance(){
		return null;
	}
}</span>

上面的代码 getInstance()方法返回的是null对象,这肯定是不对的,必须要返回SingleTon类的实例对象,那么创建对象可以在一开始就创建,还有一种就是在运行期间创建,这就是所谓单例模式的懒汉式和饿汉式


首先讲讲饿汉式,因为这个最简单:

package cn.handcool.singlton;
public class SingleTon {
private static SingleTon instance = new SingleTon();
private SingleTon(){}
public static SingleTon getInstance(){

return instance;
}
}

懒汉式:


package cn.handcool.singlton;
public class SingleTon {
private static SingleTon instance ;
private SingleTon(){}
public static SingleTon getInstance(){
if(null==instance){
instance = new SingleTon();
}
return instance;
}
}

在java中有延迟加载的概念,懒汉式就是使用了延迟加载的思想

通俗点说,就是一开始不要加载资源或者手机,一直等到马上就要使用这个资源或者数据了,才去加载
所以也称lazy load,这个在实际开发中是一种很常见的思想,尽可能的节约资源


而懒汉式的延迟加载提现在那呢?

if(null==instance){
instance = new SingleTon();
}

上面的代码是只有去调用getInstance()方法才去创建SingleTon对象实例,如果不调用就不会创建对象,相对饿汉式就是一种延迟加载了,因为它不像饿汉式那样,一上来就创建对象缓存在内存中


懒汉式提现了java中的缓存思想,这在java中也有很多,比如android中加载图片,就是使用了缓存的思想,可以缓存在内存,或者sd卡以及其他存储空间,


缓存的思想:

简单的来讲,就是某些资源或者数据被频繁的使用,就不必每次访问网络去获取这些数据,第一效率会低,第二:节省了用户的流量,那我们就可以把这些数据缓存到内存中,每次操作到内存中 去找,内存中没有,就走网络去获取,第一次从网络获取后要设置到内存中,方便下次使用,缓存是一种典型的空间换时间的方案.


在java中一般使用集合来实现缓存,先看简单的例子:

JavaCache.java

<span style="font-size:24px;">/**
 * Java中缓存的基本实现示例
 */
public class JavaCache {

	public static Map<String,Object> map = new HashMap<String,Object>();
	/**
	 * 从缓存中获取值
	 * @param key 设置时候的key值
	 * @return key对应的Value值
	 */
	public static Object getValue(String key){
		//先从缓存里面取值
		Object obj = map.get(key);
		//判断缓存里面是否有值
		if(obj == null){
			//如果没有,那么就去获取相应的数据,比如读取数据库或者文件
			//这里只是演示,所以直接写个假的值
			obj = key+",value";
			//把获取的值设置回到缓存里面
			map.put(key, obj);
		}
		//如果有值了,就直接返回使用
		return obj;
	}
}</span>
<span style="font-size:24px;">Client.java</span>
<span style="font-size:24px;">public class Client {
  public static void main(String[] args) {
   JavaCache.map.put("a", "a");
   JavaCache.map.put("b", "b");
   JavaCache.map.put("c", "c");
   JavaCache.map.put("d", "d");
   
   System.out.println(JavaCache.getValue("a"));
   System.out.println(JavaCache.getValue("b"));
   System.out.println(JavaCache.getValue("e"));
  }
}</span>
<span style="font-size:24px;">运行结果:</span>
<span style="font-size:24px;">a
b
e,value</span>
<span style="font-size:24px;">在map集合并没有存放key为"e"对应的值</span>
<span style="font-size:24px;">代码如下:</span>
<span style="font-size:24px;"></span>

<span style="font-size:24px;"></span>
<span style="font-size:24px;">if(obj == null){
			System.out.println("zou");
			//如果没有,那么就去获取相应的数据,比如读取数据库或者文件
			//这里只是演示,所以直接写个假的值
			obj = key+",value";
			//把获取的值设置回到缓存里面
			map.put(key, obj);
		}</span>

然后保存大哦哦map集合中,下次获取key为"e"的值就在map集合中了,


缓存的基本实现:

1:定义一个存放缓存数据的容器

2:先从缓存里面取值

3:判断缓存里面是否有值

4:如果有值了,就直接使用这个值

5:如果没有,那么就去获取相应的数据,或者是创建相应的对象

6:把获取的值设置回到缓存里面


现在利用缓存模拟单例的实现

Singleton.java

<span style="font-size:24px;">/**
 * 使用缓存来模拟实现单例
 */
public class Singleton {
	/**
	 * 定义一个缺省的key值,用来标识在缓存中的存放
	 */
	private final static String DEFAULT_KEY = "One";
	/**
	 * 缓存实例的容器
	 */
	private static Map<String,Singleton> map = new HashMap<String,Singleton>();
	/**
	 * 私有化构造方法
	 */
	private Singleton(){
		//
	}
	public static Singleton getInstance(){
		//先从缓存中获取
		Singleton instance = (Singleton)map.get(DEFAULT_KEY);
		//如果没有,就新建一个,然后设置回缓存中
		if(instance==null){
			instance = new Singleton();
			map.put(DEFAULT_KEY, instance);
		}
		//如果有就直接使用
		return instance;
	}
	
}</span>

上面就是使用缓存来实现单例模式的,也能确保类的实例仅有一个

现在从安全问题考虑单例的二种现实方式

1:饿汉式 这种是没有线程安全问题的,因为在getInstance()方法中直接返回了SingleTon对象,线程安全产生的条件是多个线程执行了同一段代码,但是饿汉式只有一行代码,所以不存在线程安全问题

2:懒汉式会出现安全问题,那我们分析分析怎么会出现安全问题

主要代码如下:

<span style="font-size:24px;">public static SingleTon getInstance(){
		if(null==instance){
			instance = new SingleTon();
		}
		return instance;
	}</span>
<span style="font-size:24px;">
</span>

比如说有A,B线程同时调用getInstance()方法

A线程执行到了 new SingleTon();但是并没有赋值给instance,这个时候刚好有个B线程进来,因为new的对象没有赋值给instance变量,所以instance还是为null,因此B线程还是会走if语句,那么这个时候A和B都是new SingleTon();对象并赋值给instance,那就是创建了2个对象了,和单例模式的定义并不符合,这就是懒汉式导致的线程安全问题,既然出现了问题,那么我们就想办法解决,

在线程中解决安全问题通常有2种方法

1:使用同步代码块

2:使用同步方法


如果使用同步方法解决安全问题,这很简单直接在getInstance()方法中添加synchronized关键字就可以,代码如下:

<span style="font-size:24px;">public synchronized static SingleTon getInstance(){
		if(null==instance){
			instance = new SingleTon();
		}
		return instance;
	}</span>
<span style="font-size:24px;">通过加一个关键字synchronized就轻而易举的解决了线程安全问题,问题解决了,那有没有比这更高效的方法呢?答案是有</span>
<span style="font-size:24px;">双重检查加锁判断比使用同步方法更高效</span>
<span style="font-size:24px;">所谓双重检查加锁机制,指的是:并不是每次进入getInstance()方法都需要同步,而是先不同步,进入方法后,先检查实例对象是否存在,如果不存在才进入下面的同步代码块,这是第一次检查,进入同步代码块后,再次检查实例对象是否存在,如果不存在,就在同步的情况下创建实例对象,这是第二次检查,这样一来,就只要同步一次了,从而减少了多次在同步情况下进行判断浪费时间</span>
<span style="font-size:24px;">
</span>
<span style="font-size:24px;">这就是双重检查加锁比同步方法效率更高德原因</span>
<span style="font-size:24px;">
</span>
<span style="font-size:24px;">代码如下:</span>
<pre class="java" name="code"><span style="font-size:24px;">public static  Singleton getInstance(){
		//先检查实例是否存在,如果不存在才进入下面的同步块
		if(instance == null){
			//同步块,线程安全的创建实例
			synchronized(Singleton.class){
				//再次检查实例是否存在,如果不存在才真的创建实例
				if(instance == null){
					instance = new Singleton();
				}
			}
		}
		return instance;
	}</span>
<span style="font-size:24px;">总结:使用双重检查加锁只需要同步一次创建了对象后,其他时候就不需要同步了,直接返回创建的对象实例即可!</span>
















java设计模式之单例模式——Singleton pattern 设计模式故事会:https://blog.youkuaiyun.com/weixin_40205234/article/details/90664824 单例模式 单例模式(Singleton pattern)是java中最常见的设计模式之一。该模式属于创建型设计模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一... 阅读详情

相关推荐

从BIN文件到可烧录程序:深入理解ADI DSP程序读取背后的原理与安全边界

本文深入探讨了ADI DSP程序从BIN文件到可烧录程序的转换原理与安全边界,详细解析了JTAG接口、仿真器工作流程及Flash存储结构。通过Visual DSP++工具,开发者可以理解程序读取的底层机制,同时强调了知识产权保护的重要性,为嵌入式开发提供了实用建议。

weixin_27956639的博客 263

设计模式-单例模式(Singleton Pattern)

单例模式 定义 确保一个类只有一个实例,并为整个系统提供一个全局访问点 (向整个系统提供这个实例)。 类型 创建型。 适用场景 网站访问量计数器。 项目中用于读取配置文件的类。 Spring中,每个Bean默认都是单例的,这样便于Spring容器进行管理。 优点 由于单例模式只生成了一个实例,所以能够节约系统资源、减少性能开销、提高系统效率。 缺点 不适合用于变化频繁的对象;如果实例化的对象长...

kaven 5158

用友T3提示,年度[UFDATA_002_2017]并不存在,导致无法备份迁移。

用友T3提示,年度[UFDATA_002_2017]并不存在,导致无法备份迁移。现在都win11了某个年度账套不存在怎么办?

雨季余静的博客 3561

23种设计模式中的单例模式(Singleton Pattern)

本篇文章将23种设计模式中的单例设计模式,此篇文章为一天学习一个设计模式系列文章,后面会分享其他模式知识。

小威的博客 2万+

【Azure 架构师学习笔记】- Azure Databricks (1) - 环境搭建

Databricks 已经成为了数据科学的必备工具,今时今日你已经很难抛开它来谈大数据,它常用于做复杂的ETL中的T, 数据分析,数据挖掘等,特别适用于做数据建模,机器学习等。那么顺应时代,现在也来看看这个工具的内容。首先要有一个环境,基于Azure 的Databricks简称ADB。托管在Azure 上的Databricks已经被Azure进行了很大的优化, 在搭建时只需要简单的几步即可拥有一个环境,不过要提醒一句ADB的集群并不便宜,用完马上删掉或停止, 否则一晚过百美金就会烧掉。

MVP黄钊吉(發糞塗牆) 2298

Vue路由守卫实战:利用token实现跨项目免登录跳转(最新版)

本文详细介绍了如何利用Vue路由守卫和Token验证实现跨项目免登录跳转方案。通过核心架构设计、路由守卫精细化控制及Token交换安全实践,有效解决了多系统跳转中的认证问题,提升用户体验和系统连贯性。

n7o8p的博客 137

设计模式之单例模式(Singleton Pattern)

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。主要解决:一个全局使用的类频繁地创建与销毁。何时使用:当您想控制实例数目,节省系统资源的时候。如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。关键代码:构造函数是私有的。

weixin_42294716的博客 1398

Python爬虫实战:高效爬取Vimeo高清视频

在当今数字化时代,视频内容已成为互联网的重要组成部分。Vimeo作为一个高质量的视频分享平台,拥有大量优质视频资源。然而,Vimeo并未提供直接下载视频的选项,因此,我们需要借助Python爬虫技术来获取这些高清视频。(HTTP Live Streaming)格式存储。Vimeo的视频通常不会直接暴露。Vimeo的视频通常以。

2201_76125261的博客 429

23种设计模式之单例模式(Singleton Pattern)【设计模式】

📒单例模式(Singleton Pattern)是一种创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式主要用于控制资源的访问,确保某些类只有一个实例,并且这个实例能够被全局访问。

李赛赛的专栏 1101

手把手教你学Simulink--基于Simulink的高增益DC-DC变换器仿真建模

特点高电压增益:可以在不使用变压器的情况下实现较大的电压升压比。适用于低电压源:如太阳能电池板、燃料电池等提供的低压直流电源。效率问题:设计时需特别注意提高效率,减少能量损失。挑战电路复杂性:通常涉及多个电感和电容,以及复杂的开关模式。元件选择:合适的元件参数对于达到理想性能至关重要。控制策略:确保高效稳定运行的同时,适应负载变化。首先明确要模拟的任务内容。实现特定的电压增益比(例如从24V升至380V)。根据预期的输入输出电压确定合适的电路拓扑和元件值。

MHD0815的博客 173

7.1华为OD机试真题 新系统 - 仓库盘点 (Java/Py/C/C++/Js/Go)

7.1华为OD机试真题 新系统 - 仓库盘点 (Java/Py/C/C++/Js/Go)

算法大师! 507

设计模式:单例模式(Singleton Pattern)

单例模式(Singleton Pattern)是一种创建型设计模式,它的核心思想是:保证在一个进程中,某个类仅有一个实例,并提供全局访问点。

TechNomad的博客 1456

基于 YOLOv26 的陶瓷产品缺陷检测系统:智能视觉质检方案

本文提出了一种基于YOLOv26深度学习模型的陶瓷产品智能缺陷检测系统。该系统针对陶瓷生产中的裂纹、气泡、釉面缺陷等8类常见质量问题,采用YOLOv26目标检测算法实现高精度自动化检测。系统架构包含数据采集、预处理、YOLOv26检测和后处理四个模块,具有多类别分类、实时推理和强鲁棒性等技术优势。文章详细介绍了数据预处理与增强方法,并提供了Python代码实现示例。该方案可显著提升陶瓷产品质量检测效率,替代传统人工检测方式,为陶瓷制造业提供智能化质检解决方案。

一键难忘的博客 787

设计模式——单例模式(Singleton Pattern)

设计模式——单例模式(Singleton Pattern) 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在有些场景中,为了节省内存资源、保证数据内容的一致性,对某些类要求只能创建一个实例,且该类能自行创建这个实例,这就是所谓的单例模式 文章目录设计模式——单例模式(Singleton Pattern)单例模式的优缺点优点缺点单例模式的应用场景单例模式与静态类的区别常见的7种实现方式1.饿汉模式2.懒

qq_42498542的博客 833

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

实践GoF设计模式:Singleton Pattern 单例模式

前言 我们在开发项目中,经常会遇到这种情况,为了节约所拥有的系统资源或数据的一致性时,需要保证系统中的某个类中有且只有唯一的一个实例,而且在其创建成功之后,我们将不能再次创建同类型的其他对象,也就是所有的操作都要以这个唯一的实例为中心,所以为了保证对象所具有的的唯一性,单例模式成为我们所具备的方法 概念 ● 设计模式中单例模式是最为简单的形式之一,而且是使用最广泛的设计模式之一,其目的是为了将类的一个对象成为系统中的唯一实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享 ● 要想实现这一点,可以

m0_70748458的博客 402

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

设计模式总结之Singleton Pattern(单例模式)

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

cooldragon的专栏 4858

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

golang mysql单例模式_GoLang 设计模式之单例模式 (Singleton Pattern)

软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设 计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。???? 单例模式 (Singleton Pattern)现实世界的例子:一次只能有一个国家的总统。简单来说:确保只创建特定类的一个对象。单例模式实际上被认为是反模式,应该避免过度使用它。它不...

weixin_39924573的博客 281

设计模式——单例模式(Singleton Pattern)+ Spring相关源码

确保一个类只有一个实例,并提供了一个全局访问点来访问该实例。避免一个全局使用的类频繁地创建与销毁。

码鹿的记录 367

【Java设计模式】之 单例模式(Singleton Pattern)模式 饿汉式单例模式 vs 懒汉式单例模式

什么是设计模式? 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模免去我们自己再思考和摸索,设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,"套路”。 设计模式的分类: ① 创建型模式(5种):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 ② 结构型模式(7种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。 ③ 行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、

weixin_46081857的博客 418

JavaScript 设计模式之-单例模式(Singleton Pattern)

面试了很多简历写着前端5,6年高级前端工程师,大部分设计模式都说不明白,其实不要把设计模式想的很难,其实是一种思想,我一起搞iOS,也搞前端,设计模式原理都是一样的,写法就不差不多,只要搞清楚他的概念和使用场景就理解很容易 什么是单例模式? 规定一个类只有一个实例,并且提供可全局访问点; 单例模式的有哪些使用场景? 就APP 开发来说,单例模式还是比较常用的,比如弹窗组件,通过全局单例维护相关状态,如果每次创建一个新的对象,有些场景会多个弹窗叠加。 还有定位,或者网络请求,都是使用单例进行封装的。 例如.

冷胜任 的专栏 526

设计模式之单例模式(Singleton pattern)

单例模式是一种常用的软件设计模式,通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。 看代码: 1 namespace SingletonPattern 2 { 3 public class Singleton 4 { ...

144

设计模式---单例模式(DesignPattern_Singleton)

DesignPattern_AbstractFactory 摘录自:设计模式与游戏完美开发 工程GitHub SINGLETON—俺有6个漂亮的老婆,她们的老公都是我,我就是我们家里的老公Singleton,她们只要说道“老公”,都是指的同一个人,那就是我(刚才做了个梦啦,哪有这么好的事) 单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例...

su9257的博客 145
上一篇: 有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中
下一篇: java中成员变量和局部变量的区别
zhoushenxian
博客等级 码龄12年 453粉丝 549原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值