【设计模式】单例模式|最常用的设计模式

news2025/1/15 13:44:19

写在前面

单例模式是最常用的设计模式之一,虽然简单,但是还是有一些小坑点需要注意。本文介绍单例模式并使用go语言实现一遍单例模式。

单例模式介绍

简介

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

使用场景:

  1. 当类只能有一个实例而且可以从一个公开的众所周知的访问点访问它。
  2. 当这个唯一实例是通过子类化可扩展的,并且应该无须更改单例代码就能使用一个扩展的实例。

结构图
在这里插入图片描述

分类

单例里面分成了两种模式,一种是饿汉式,一种是懒汉式。

饿汉式

饿汉模式下的单例,只在使用实例的时候就创建了对象。
代码实例:

var req *Request

type Request struct {
}

func NewRequest() *Request {
	if req == nil {
		req = new(Request)
	}
	return req
}

这个代码看起来没什么问题,但是这段代码是线程不安全的。 因为如果有多个请求过来,就会同时创建多个对象,就会出现频繁的创建和删除对象,给gc造成很大的压力。

当然我们也可以加锁,但是频繁的加锁,解锁会严重影响系统的性能。

var req *Request
var lock sync.Mutex

type Request struct {
}

func NewRequest() *Request {
	lock.Lock()
	defer lock.Unlock()
	if req == nil {
		req = new(Request)
	}
	return req
}

每一个对象的创建,都需要加锁解锁,非常影响性能

懒汉式

懒汉式的单例模式可以解决我们饿汉式的缺点,并且是线程安全的,保证了我们对象全局唯一并且不会重复创建。

代码如下:

var req *Request
var reqOnce sync.Once

type Request struct {
}

func NewRequest() *Request {
	reqOnce.Do(func() {
		req = &Request{}
	})

	return req
}

这里我们用到go语言的 sync.Once 包,而sync.Once的作用就是使得我们的函数只执行一次。并且是并发安全的。

那为什么是并发安全的呢?接下来我们详解一下 sync.Once

sync.Once

sync.once 内部原理很简单,Once的结构题如下:

type Once struct {
    // done变量用来标识函数是否执行完毕
    done uint32
    // m用来保证函数执行期间,其他goroutine阻塞
    m    Mutex
}

这个Do方法是判断有无执行过这个该方法,并且是使用atomic.LoadUint32的原子操作。

func (o *Once) Do(f func()) {
    // 1.判断函数是否执行过,done=0说明没执行过
    if atomic.LoadUint32(&o.done) == 0 {
        o.doSlow(f)
    }
}
  1. 如果没执行过就执行这个方法,那么这里会有一个double check的工作,其实就是防止可能在上一次检查到这一次加锁加完的时间段间隙上有人执行完了这个函数

  2. 确认确实没有执行的时候,就执行函数,并进行原子操作标识,将 done 置为1。

func (o *Once) doSlow(f func()) {
    // 1.加锁
    o.m.Lock()
    // 5.函数返回后,释放锁
    defer o.m.Unlock()
    // 2.判断是否执行过
    if o.done == 0 {
        // 4.函数返回后,设置执行标识
        defer atomic.StoreUint32(&o.done, 1)
        // 3.具体执行函数
        f()
    }
}

应用场景举例子

我们可以在 service 上定义某一个方法的结构体函数,并将可以根据这个结构体函数进行方法的扩展。
在这里插入图片描述
在controll层只需要调用这个函数方法即可GetUserSrv()

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

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

相关文章

超市火灾烟雾蔓延及人员疏散的matlab模拟仿真,带GUI界面

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 出口在人员的视野范围内时,该元胞选择朝向引导点的方向运动。出口不在人员的视野范围内时,作随机运动,8个方向的运动概率相等。…

短视频素材怎么做?视频素材库那个好?

在这个视频内容占据主导的时代,高质量的无水印视频素材不仅能够丰富视觉体验,还能显著提升你的作品吸引力。为了帮助你在广阔的创意海洋中航行,下面介绍的一系列视频素材网站将为你的项目注入新的活力,让每个创意的火花都能闪耀发…

Spring Boot集成Redisson实现延迟队列

项目场景: 在电商、支付等领域,往往会有这样的场景,用户下单后放弃支付了,那这笔订单会在指定的时间段后进行关闭操作,细心的你一定发现了像某宝、某东都有这样的逻辑,而且时间很准确,误差在1s内…

K-近邻算法的 sklearn 实现

实验目的与要求 掌握基于 K-近邻分类算法的编程方法通过编程理解 K-近邻分类算法和该算法的基本步骤 实验器材 硬件:PC 机(参与实验的学生每人一台)软件环境:Python3.7 Pycharm 实验内容 使用 sklearn 库中的 neighbors 模块实…

【java、maven环境变量配置问题】

这里写目录标题 软件版本查询所遇问题及解决方法1、java环境变量修改后不起效果:变量值2、java环境变量修改后不起效果:变量名结论: 软件版本查询 查询 java jdk 版本:java -version 查询 maven 版本: mvn -v 所遇问…

如何安装最新版Docker Compose?

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YAML 文件来配置应用服务,然后只需一个简单的命令便能创建和启动所有服务。在本篇博客中,我们将详细介绍如何在 Linux 系统上安装 Docker Compos…

恭喜!喜提美国匹兹堡大学儿童医院访问学者邀请函

➡️【院校简介】 匹兹堡UPMC儿童医院该院是匹兹堡大学医学中心的一部分,也是大匹兹堡唯一一家专门护理26岁以下婴儿,儿童,青少年和年轻人的医院。该医院隶属于匹兹堡大学医学院,设有一个获得州级认证的一级儿科创伤中心&#xf…

ESP32开发WebSocket报错TRANSPORT_WS: Sec-WebSocket-Accept not found

我的芯片是ESP32-S3,用ESP-IDF框架进行开发的时候,用官方的WebSocket的example创建了项目。然后把WebSocket连接uri替换为自己的服务器后,运行到esp_websocket_client_start开始连接后,直接报错: E (10615) TRANSPORT…

C++|运算符重载(3)|日期类的计算

前面介绍了运算符重载相关规则和方法&#xff0c;今天用运算重载函数实现对日期类的操作。 目录 前面准备 实现功能&#xff1a; -运算符 Date类和int 相减 Date类和Date类相减 运算符 &#xff0c;-运算符 ,!运算符 >,>运算符 <,<运算符 &#xff0c;-…

MIS微调SAM模型实时交互UI界面

前言 SAM模型的基本介绍可见SAM&#xff08;Segment Anything Model&#xff09;大模型使用--point prompt_sam大模型-CSDN博客 针对Meta团队去年发布的SAM大模型在医学图像分割领域表现性能较差的情况&#xff0c;笔者收集了一些MIS领域的数据集对SAM的架构进行fine tune&am…

银河麒麟安装SSH工具

查看22端口是否启用 netstat -ntlp|grep 22 二、安装SSH工具 1、安装openssh 执行指令# sudo apt-get install openssh-server 2、更新ubuntu源 执行指令# sudo apt-get update 3、安装openssh-server 执行指令# sudo apt-get install openssh-server 4、安装ufw防火…

分享:抖音阳哥说的人力RPO项目有哪些优势?

在数字化浪潮的推动下&#xff0c;人力资源行业也迎来了前所未有的变革。抖音平台上&#xff0c;阳哥以其独到的见解和丰富的经验&#xff0c;对人力RPO(招聘流程外包)项目进行了深入解读。今天&#xff0c;我们就来探讨一下人力RPO项目究竟有哪些优势。 人力RPO项目的一大优势…

【C语言__联合和枚举__复习篇10】

目录 前言 一、联合体 1.1 联合体的概念 1.2 联合体与结构体关于声明和内存布局的比较 1.3 联合体的大小如何计算 1.4 使用联合体的2个示例 二、枚举体 2.2 枚举体的概念 2.2 枚举体的优点 前言 本篇主要讨论以下问题&#xff1a; 1. 联合体是什么&#xff0c;它有什么特点 …

SpringMVC笔记——SpringMVC基础Tomcat环境配置

Tomcat安装配置 下载Apache Tomcat 进入官网https://tomcat.apache.org/&#xff0c;选择tomcat 9 这边使用idea开发&#xff0c;建议直接下载压缩包 无法访问下载的可以直接用我的下载链接&#xff1a;https://cloudreve.zxbdwy.online/s/6nSA 提取码&#xff1a;w1pwk3将压…

玩转微服务-SonarQube

这里写目录标题 第一节 SonarQube1.1 简介1.2 四个组成部分1.2.1 SonarQube服务器1.2.2 SonarQube数据库1.2.3 插件1.2.4 Scanner 1.3 工作流程 第二节 SonarQube的安装2.1 安装2.2 插件 第三节 P3C规范3.1 简介3.2 SonarQube 配置 P3C规范3.3 IDEA配置 P3C规范 第四节 Maven项…

基于opencv的单目相机标定

openCv版本&#xff1a;4.4.0 从源码处拷贝标定代码出来使用&#xff0c;需要拷贝samples/cpp/tutorial_code/calib3d/camera_calibration 需要的文件如下&#xff1a; -rw-rw-r-- 1 rog rog 28490 Jul 18 2020 camera_calibration.cpp -rw-rw-r-- 1 rog rog 3152 Jul 18 …

初识C++·类和对象(中)(3)

前言&#xff0c;最难的已经结束了&#xff0c;来点轻松了放松一下。 目录 1 流重载 2 const成员 3 取地址及const取地址操作符重载 1 流重载 C语言中printf和scanf是有局限性&#xff0c;只能直接打印内置类型&#xff0c;对于自定义类型就哦豁了&#xff0c;所以在C中就…

5月计算机各省报名时间汇总报名流程

&#x1f4e3;5月有5省可进行计算机报名 天津&#xff1a;5月6日-5月10日 福建&#xff1a;5月6日9:00-5月12日17:00 广西&#xff1a;5月6日9:00-5月12日23:55 重庆&#xff1a;5月6日9:00-5月12日24:00 西藏&#xff1a;预计5月6日-12日 &#x1f50d;计算机等级考试报…

linux DNS域名解析服务

目录 一.DNS DNS系统的作用 域名结构&#xff1a; 根域 顶级域 二级域 子域 主机 二.DNS解析过程 迭代查询&#xff1a; 递归查询&#xff1a; 三.实验模拟 主、从服务器设置 1.搭建本地DNS服务器------(主服务器配置) 1&#xff09;初始化系统 ​编辑2&#xf…

win c++使用lua环境配置 5.3.5版本

编译lua 下载lua源码&#xff0c;github仓库 使用vs编译源码&#xff0c;新建一个静态库项目(只会生成lib文件)&#xff0c;想要dll的话就新建dll项目&#xff08;有一个lib文件和dll文件&#xff09; 把lua源码下面的文件夹都是&#xff0c;复制到vs项目中 lib目录是我手动…