当前位置: 首页 > news >正文

【设计模式】创建型模式之单例模式(饿汉式 懒汉式 Golang实现)

定义

一个类只允许创建一个对象或实例,而且自行实例化并向整个系统提供该实例,这个类就是一个单例类,它提供全局访问的方法。这种设计模式叫单例设计模式,简称单例模式。

单例模式的要点:

  1. 某个类只能有一个实例
  2. 必须自行创建该实例
  3. 必须自行向整个系统提供该实例
    在这里插入图片描述
    时序图:
    在这里插入图片描述

用处

从业务概念上来看,有些数据在系统中只应该保留一份,就比较适合设计为单例类。比如,系统的配置信息。

使用场景:

  • 系统只需要一个实例对象,比如唯一的序列号生成器(业务方面),或是考虑到资源消耗太大而只允许创建一个对象
  • 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点外,不能通过其他途径访问该实例

优缺点

优点:

  • 提供了对唯一实例的受控访问
  • 因为在系统的内存里只存在一个对象,所以可以节约系统资源,尤其是一些需要频繁创建和销毁的对象
  • 允许可变数目的实例,基于单例模式进行扩展

缺点:

  • 没有抽象层,很难扩展
  • 职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。

单例模式的唯一性

  1. 进程间唯一:默认单例模式的唯一性就是基于进程的唯一性。因为编写的代码成为可执行文件后,当运行该可执行文件时,操作系统会启动一个进程,将该可执行文件从磁盘加载到自己的进程地址空间,该进程依次执行文件中的代码,比如代码里有一个创建student对象的语句,进程就会在地址空间里创建一个student对象。如果在一个进程中创建另一个进程,操作系统会给新进程分配新的地址空间,而且将旧地址空间的内容拷贝一份,包括代码和数据,这样新进程里有且只有一个student对象,旧进程里也有且只有一个student,但是这两个对象并不是同一个对象。
  2. 线程间唯一:通过获取线程id来实现。但是在golang里主要使用协程,而且协程的id并不会暴露出来。
  3. 集群环境间唯一(多进程):通过外部共享存储的锁进行,如文件。将单例对象序列化后存储到外部共享存储区里(比如文件),进程在使用该单例对象的时候,需要对该单例对象加锁,避免其他进程再获取,然后将该对象加载到内存里,反序列化为单例对象,使用完后还要从内存里删除,再存储回外部共享存储区,并释放锁。

如何实现

  • 构造函数是private访问权限
  • 考虑对象创建时的线程安全问题
  • 考虑是否支持延迟加载
  • 考虑getInstance的性能问题,比如是否有加锁等

实现方式

饿汉式

在类加载的时候实例就已经创建好了,实例的创建过程线程安全,不支持延迟加载

有两种实现方式,第一种是定义全局变量的时候创建实例,第二种是采用包的init函数创建实例

注意这里的Singleton类型也要是大写字母开头的,因为GetInstance方法是大写字母开头,表明包外可访问,那么该方法的返回值也需要包外可访问。

package singleton// 单例模式 饿汉式实现
type Singleton struct{}var singleton *Singleton//1.全局变量的实现方式
//var singleton1 = &Singleton{}
//2. 包的init函数实现方式
func init() {singleton = &Singleton{}
}func GetInstance() *Singleton {return singleton
}

懒汉式

在获取实例的时候再去创建,实例创建过程需要加锁,支持延迟加载,不支持高并发

不加锁

只是对懒汉式创建的一个理解,在GetInstnce方法里判断singleton是否为空,为空的话就去创建一个实例,否则直接返回该实例。

存在线程安全问题,高并发的时候会创建多个对象,不推荐使用。

package singleton// 单例模式 懒汉式实现 不加锁
type Singleton struct{}var singleton *Singletonfunc GetInstance() *Singleton {if singleton == nil {singleton = &Singleton{}}return singleton
}

给方法加锁

GetInstance整个方法进行加锁,确保并发安全,但是每一个对象创建的时候都需要进行加锁解锁,效率低

package singletonimport "sync"// 单例模式 懒汉式实现 方法锁
type Singleton struct{}var singleton *Singleton
var mu sync.Mutexfunc GetInstance() *Singleton {mu.Lock()defer mu.Unlock()if singleton == nil {singleton = &Singleton{}}return singleton
}

双重检测

在懒汉式的基础上,将方法的锁改为类级别的锁,相对于懒汉式的粒度更小,不用每次都去获取锁

借助sync.Once确保只创建一次

package singletonimport "sync"// 单例模式 懒汉式实现 双重检测
type LazySingleton struct{}var lazySingleton *LazySingleton
var once = &sync.Once{}func GetLazyInstance() *LazySingleton {if lazySingleton == nil {once.Do(func() {lazySingleton = &LazySingleton{}})}return lazySingleton
}

静态内部类

java的静态内部类,线程安全,延迟加载

枚举

java的枚举特性

测试性能

测试饿汉式的init实现方法和懒汉式的sync.Once实现方法

package singletonimport "testing"func BenchmarkGetInstanceParallel(b *testing.B) {b.RunParallel(func(pb *testing.PB) {for pb.Next() {if GetInstance() != GetInstance() {b.Errorf("test fail")}}})
}func BenchmarkGetLazyInstanceParallel(b *testing.B) {b.RunParallel(func(pb *testing.PB) {for pb.Next() {if GetLazyInstance() != GetLazyInstance() {b.Errorf("test fail")}}})
}

在对应的目录下执行:

go test -bench='Parallel$' -benchmem .

在这里插入图片描述
可以看出饿汉式的性能更好一点

参考链接
图解设计模式
Go设计模式
Golang单例模式

相关文章:

【设计模式】创建型模式之单例模式(饿汉式 懒汉式 Golang实现)

定义 一个类只允许创建一个对象或实例,而且自行实例化并向整个系统提供该实例,这个类就是一个单例类,它提供全局访问的方法。这种设计模式叫单例设计模式,简称单例模式。 单例模式的要点: 某个类只能有一个实例必须…...

使用 Docker Compose 来编排部署LMTNR项目

使用 Docker Compose 来部署一个包含 Linux、MySQL、Tomcat、Nginx 和 Redis 的完整项目的例子。假设我们要部署一个简单的 Java Web 应用,并且使用 Nginx 作为反向代理服务器。 项目目录结构 首先需要确保 Docker 和docker-compose已经安装并正在运行。docker --v…...

创建HTTPS网站

每天,我们都会听到网络上发生身份盗窃和数据侵权的案例,这导致用户对自己访问的网站更加怀疑。他们开始更加了解自己将个人信息放在哪里以及信任哪些类型的网站。了解如何使网站使用HTTPS变得比以往任何时候都更加重要。 解读缩略词:HTTP与HT…...

以3D数字人AI产品赋能教育培训人才发展,魔珐科技亮相AI+教育创新与人才发展大会

11月20日,北京中关村国际创新中心迎来了“AI教育创新与人才发展大会暨首届北京数字人才发展大会”的盛大启幕。此次大会汇聚了培训、教育、科技、人才领域的专家学者、行业领袖及企业代表,共同探讨人工智能技术在教育培训领域的革新应用与数字人才培养体…...

springboot配置https,并使用wss

学习链接 springboot如何将http转https SpringBoot配置HTTPS及开发调试 Tomcat8.5配置https和SpringBoot配置https 可借鉴的参考: springboot如何配置ssl支持httpsSpringBoot配置HTTPS及开发调试的操作方法springboot实现的https单向认证和双向认证(java生成证…...

Qt SQL模块概述

Qt SQL支持的数据库 要在项目中使用 Qt SQL 模块&#xff0c;需要在项目配置文件中添加下面一条设置语句&#xff1a; Qt sql在头文件或源文件中使用 Qt SQL 模块中的类&#xff0c;可以使用包含语句&#xff1a; #include <QtSql>这样会将某个 Qt SQL 模块中的所有类…...

JavaWeb后端开发知识储备2

目录 1.HttpClient 2.微信小程序开发 3.Spring Cache 4.Spring Task 4.1cron表达式 4.2入门案例 5.WebSocket协议 1.HttpClient 简单来说&#xff0c;HttpClient可以通过编码的方式在Java中发送Http请求 2.微信小程序开发 微信小程序的开发本质上是前端开发&#xff0…...

RabbitMQ原理架构解析:消息传递的核心机制

文章目录 一、RabbitMQ简介1.1、概述1.2、特性 二、RabbitMQ原理架构三、RabbitMQ应用场景3.1、简单模式3.2、工作模式3.3、发布订阅3.4、路由模式3.5 主题订阅模式 四、同类中间件对比五、RabbitMQ部署5.1、单机部署5.2、集群部署&#xff08;镜像模式&#xff09;5.3、K8s部署…...

redmi 12c 刷机

刷机历程 一个多月前网购了redmi 12c这款手机, 价格只有550,用来搞机再适合不过了, 拆快递后就开始倒腾,网上有人说需要等7天才能解锁,我绑定了账号过了几天又忍不住倒腾,最后发现这块手机不用等7天解锁成功了,开始我为了获取root权限, 刷入了很火的magisk,但是某一天仍然发现/…...

四、Python —— 列表

文章目录 一、列表的初始化1.1、直接初始化1.2、通过 append 函数初始化1.3、 通过 for 语句初始化列表长度和每个位置的数值 二、访问列表元素2.1、越界的含义 三、 使用循环语句遍历列表3.1、通过下标遍历3.2、通过 for...in... 直接遍历 四、列表的切片操作五、列表的复制六…...

Paper -- 建筑高度估计 -- 基于街景图像和深度学习的城区建筑高度计算

基本信息 论文题目: Building height calculation for an urban area based on street view images and deep learning 中文题目: 基于街景图像和深度学习的城区建筑高度计算 作者及单位: – Zhen Xu Furong Zhang Yingying Wu Yajun Yang Yuan Wu – 北京科技大学城市与安全研…...

机器学习周志华学习笔记-第6章<支持向量机>

机器学习周志华学习笔记-第6章<支持向量机> 卷王&#xff0c;请看目录 6支持向量机6.1 函数间隔与几何间隔6.1.1 函数间隔6.1.2 几何间隔 6.2 最大间隔与支持向量6.3 对偶问题6.4 核函数6.5 软间隔支持向量机6.6 支持向量机6.7核方法 6支持向量机 支持向量机是一种经典…...

第三届航空航天与控制工程国际 (ICoACE 2024)

重要信息 会议官网&#xff1a;www.icoace.com 线下召开&#xff1a;2024年11月29日-12月1日 会议地点&#xff1a;陕西西安理工大学金花校区 &#xff08;西安市金花南路5号&#xff09; 大会简介 2024年第三届航空航天与控制工程国际学术会议&#xff08;ICoACE 2024&a…...

【大数据技术基础】 课程 第8章 数据仓库Hive的安装和使用 大数据基础编程、实验和案例教程(第2版)

第8章 数据仓库Hive的安装和使用 8.1 Hive的安装 8.1.1 下载安装文件 访问Hive官网&#xff08;http://www.apache.org/dyn/closer.cgi/hive/&#xff09;下载安装文件apache-hive-3.1.2-bin.tar.gz 下载完安装文件以后&#xff0c;需要对文件进行解压。按照Linux系统使用的…...

BERT 详解

BERT简介 BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是由 Google 在 2018 年提出的一种预训练语言模型。BERT 在自然语言处理&#xff08;NLP&#xff09;领域取得了重大突破&#xff0c;因为它能够有效地捕捉文本的上下文信息&am…...

使用 MySQL 的 REPLACE() 函数轻松替换表中字段

前言 在数据库操作中&#xff0c;经常需要对存储的数据进行一些处理和修改&#xff0c;替换字段中的部分信息。MySQL 提供了多种字符串函数来帮助开发者完成这些任务。其中一个非常实用的函数就是 REPLACE()。 REPLACE() 函数简介 REPLACE() 函数用于在字符串中查找指定的子…...

Http 响应协议

HTTP的响应协议 响应数据格式 响应行 响应数据的第一行&#xff0c;包括协议、状态码、描述 响应头 从响应数据格式的第二行开始&#xff0c;也是以key:value的格式 响应体 和响应头之间有一个空行&#xff0c;是响应数据格式的最后一部分&#xff0c;用于存放响应的数据 常见响…...

TCP/IP 协议:网络世界的基石(2/10)

一、引言 在当今数字化时代&#xff0c;互联网已经成为人们生活中不可或缺的一部分。而在互联网的背后&#xff0c;TCP/IP 协议扮演着至关重要的角色&#xff0c;堪称互联网的基石。 TCP/IP 协议是一组用于数据通信的协议集合&#xff0c;它的名字来源于其中最重要的两个协议…...

Lua--1.基础知识

Lua基础知识 变量简单的4种变量类型复杂的4种变量类型type函数 字符串操作长度获取--#多行打印字符串拼接别的类型转字符串-- tostring()字符串提供的公共方法 运算符算术运算符-- - * / % ^条件运算符-- > < > < ~(不等于 是 ~)逻辑运算符-- and or not位运算、…...

【GPT】力量训练的底层原理?

详细解读力量训练的每一个底层原理 力量训练之所以有效&#xff0c;是因为它利用了肌肉、神经系统和生物化学反应的基本机制。以下逐一详细解析&#xff0c;并解释相关概念。 1. 应力-恢复-适应理论 概念解析 应力&#xff08;Stress&#xff09;&#xff1a;指训练带来的负…...

AT25SF041 SPI Flash驱动设计与嵌入式可靠性实践

1. AT25SF041 SPI Flash 存储器驱动深度解析AT25SF041 是由 Adesto&#xff08;现为 Dialog Semiconductor&#xff09;推出的 4 Mbit&#xff08;512 KB&#xff09;串行 NOR Flash 存储器&#xff0c;采用标准四线 SPI 接口&#xff08;CLK、CS#、DI、DO&#xff09;&#xf…...

VS Code终端切换全攻略:从PowerShell到CMD的保姆级教程(含常见问题解决)

VS Code终端切换全攻略&#xff1a;从PowerShell到CMD的保姆级教程&#xff08;含常见问题解决&#xff09; 在开发者的日常工作中&#xff0c;终端是不可或缺的工具。VS Code作为最受欢迎的代码编辑器之一&#xff0c;其内置终端功能强大且高度可定制。然而&#xff0c;许多开…...

SEO_10个提升网站排名的实用SEO技巧分享(220 )

<h1 id"seo10seo">SEO:10个提升网站排名的实用SEO技巧分享</h1> <p>在当今互联网时代&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;已经成为提升网站流量和吸引潜在客户的关键手段。百度作为中国最大的搜索引擎&#xff0c;其优化规则对整…...

告别‘阴阳屏’:深入MTK平台PQ底层,教你用代码实现多供应商屏幕色彩统一

MTK平台屏幕色彩统一实战&#xff1a;从Gamma参数调试到自动化加载 当你的项目同时采用三家不同供应商的屏幕模组时&#xff0c;用户滑动屏幕时可能看到三种截然不同的白色——这种"阴阳屏"现象在硬件采购多元化的今天越来越普遍。作为深耕显示领域多年的工程师&…...

颠覆传统系统管理的轻量级工具:NSudo如何重新定义权限操作

颠覆传统系统管理的轻量级工具&#xff1a;NSudo如何重新定义权限操作 【免费下载链接】NSudo [Deprecated, work in progress alternative: https://github.com/M2Team/NanaRun] Series of System Administration Tools 项目地址: https://gitcode.com/gh_mirrors/ns/NSudo …...

多模态数字人智能交互平台源码获取方式,支持语音克隆+实时渲染,可商用

温馨提示&#xff1a;文末有资源获取方式最近“龙虾AI”的热度很高&#xff0c;似乎人人都想养一个属于自己的数字员工。但现实是&#xff0c;这类技术对普通用户并不友好&#xff1a;部署需要代码、配置需要专人、调试更是门槛重重。更别提高昂的Token消耗&#xff0c;轻度使用…...

驾驭AI引用:Geo优化中的内容评分机制与实战策略深度解析

在生成式人工智能&#xff08;Generative AI&#xff09;日益主导信息获取与分发路径的时代&#xff0c;传统搜索引擎优化&#xff08;SEO&#xff09;的范式正被生成式引擎优化&#xff08;Geo&#xff09;所颠覆。Geo不再仅仅关注关键词排名&#xff0c;而是深入探究内容如何…...

科研加速器:GLM-4.7-Flash驱动OpenClaw自动整理文献综述

科研加速器&#xff1a;GLM-4.7-Flash驱动OpenClaw自动整理文献综述 1. 为什么需要自动化文献整理 作为每天需要阅读十几篇论文的科研工作者&#xff0c;我发现自己至少有30%的时间花在了机械性劳动上——下载PDF、重命名文件、提取关键结论、整理参考文献格式。这些工作虽然…...

如何用掩码生成蒸馏(MGD)提升小模型性能?实战ResNet-18到ImageNet分类

掩码生成蒸馏实战&#xff1a;如何让ResNet-18在ImageNet上提升1.8%准确率 在模型轻量化的浪潮中&#xff0c;知识蒸馏技术正经历着从简单模仿到特征重构的范式转变。当我们用ResNet-50这样的"大模型"指导ResNet-18等"小模型"训练时&#xff0c;传统方法往…...

MATLAB实战:手把手教你实现FM调制解调(附完整代码与避坑指南)

MATLAB实战&#xff1a;从零构建FM通信系统的完整指南 在无线通信领域&#xff0c;频率调制(FM)技术因其出色的抗噪声性能&#xff0c;至今仍广泛应用于广播、对讲机等场景。对于通信工程学生和MATLAB初学者而言&#xff0c;亲手实现一个完整的FM调制解调系统&#xff0c;是理解…...