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

写在前面

单例模式是最常用的设计模式之一,虽然简单,但是还是有一些小坑点需要注意。本文介绍单例模式并使用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()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

web自动化系列-selenium的3种弹框操作(十二)

在进行功能测试时 ,经常会遇到出现各种的弹出的提示 ,比如删除数据给出提示 、做某个操作时也会弹框给出一些友好提示 ,因为这些弹框都是做web操作时的一些常用组件 ,所以,selenium就不得不支持这些组件 。 1.弹框介绍…

HarmonyOS开发环境搭建 移动开发 鸿蒙开发 ArkTS

📜目录 💡 环境搭建 🚀安装nodejs 🤵安装ohpm 🍔安装SDK 💥Emulator安装 🌶️新建ArkTs项目 🏆️ArkTS语言 ✨️基本语法 🎈 声明式UI描述 🍱组件 …

【C语言__函数栈帧的创建和销毁__复习篇9】

目录 前言 一、知识补充 二、分析创建和销毁的过程 三、前言问题回答 前言 本篇主要讨论以下问题: 1. 编译器什么时候为局部变量分配的空间 2. 为什么局部变量的值是随机的 3. 函数是怎么传参的,传参的顺序是怎样的 4. 形参和实参是什么关系 5. 函数…

【Linux 进程间通信】管道(三)

文章目录 1.管道的五种特征2.管道的四种情况 1.管道的五种特征 ①🍎匿名管道只能用于有血缘关系的进程之间进行通信(爷孙进程之间可以进行通信),常用于父子之间进行通信; ②🍎管道内部,自带进…

若依后台管理系统(ruo-web)修改主题色,更改颜色值 (2024-04-22)

1、修改文件 setting.js 2、修改的文件路径 ruoyi-web/src/store/modules/setting.js 3、默认主题颜色 #409EFF,改新的颜色值,刷新就好了 4、修改主题颜色 还可以用户自己更换,但这个更换只是存储在浏览器中,清除缓存之后还是…

【ARM 裸机】C 语言 led 驱动

前面刚学习了汇编 led 驱动的编写和验证,现在开始就要进入 C 语言 led 驱动编写与验证了 ! 1、C 语言运行环境构建 1.1、设置处理器模式 使 6ULL 处于 SVC 模式下,之前已经提到了处理器的九种模式,参考:【ARM 裸机】汇编 led 驱…

【Linux系统编程】第六弹---权限的概念

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、什么是权限 2、权限的本质 3、Linux中的用户 4、Linux中文件的权限 4.1、文件访问者的分类(角色) 4.2、文件类型和访问权…

计算机经典黑皮书分享

计算机经典黑皮书是一套计算机科学丛书,其中包含了多本计算机科学领域的经典教材 提供了全面的知识体系:黑皮书涵盖了计算机科学的多个领域,如计算机组成与设计、操作系统、数据库、人工智能等。它们深入浅出地介绍了相关领域的基本概念、原…

WAF攻防-漏洞发现协议代理池GobyAwvsXray

知识点 1、Http/s&Sock5协议 2、Awvs&Xray&Goby代理 3、Proxifier进程代理使用 4、Safedog&BT&Aliyun防护在漏洞发现中,WAF会对三个方向进行过滤拦截: 1、速度频率问题(代理池解决) 2、工具的指纹被识别&am…

从零开始学 langchain 之搭建最小的 RAG 系统

RAG 可以说是 23 年以来到现在,最为火热的大模型应用技术了,很多人都有了很多经典的研究。而对于新人来说,有些代码十分复杂,导致只看表象并不理解其原理。今天,就利用 langchain 和大家一起搭建一个最简单的 RAG 系统…

JAVA学习笔记27(异常)

1.异常 ​ *异常(Exception) ​ *快捷键 ctrl alt t 选中try - catch ​ *如果进行了异常处理,那么即使出现了异常,程序可以继续执行 1.1 基本概念 ​ *在Java语言中,将程序执行中发生的不正常情况称为"异常"(开发过程中的语…

Xinlinx原语在哪查看如何使用/原语示例

1.打开Vivado 2.点击Tools,选择Language Templates 3.选择Language类型、Device Primitive Instantiation(原语)、Kintex-7(芯片系列),之后可以选择自己需要使用的类型,这里以分布式RAM为例&am…

大一考核题解

在本篇中,将尽力使用多种解法,来达到一题多练的效果。 1: 1.原题链接: 238. 除自身以外数组的乘积 - 力扣(LeetCode) 这道题首先一眼肯定想到拿整体的积除以当前元素,将结果作为ans,…

Mysql的【存储引擎】之【InnoDB】与【MyISAM】的区别

目录 1.存储引擎在 MyISAM 和 InnoDB 有什么区别 2.Mysql 5.7 默认的存储引擎是什么 3.一个简单例子(如果非要使用【MyISAM】存储引擎 ) 4.2009年写的留言板程序的数据(存储引擎是:【MyISAM】) 5.mysql 8.0 可以使…

Java学习笔记26(枚举和注解)

1.枚举和注解 1.1 枚举 ​ 1.枚举(enumeration) ​ 2.枚举是一组常量的集合 ​ 3.枚举属于一种特殊的类,里面只包含一组有限的特定的对象 1.枚举应用案例 ​ 1.不需要提供setXxx方法,因为枚举对象值通常为只读 ​ 2.对枚举对象/属性使用final st…

web前端(简洁版)

0. 开发环境 && 安装插件 这里我使用的是vscode开发环境 Auto Rename Tag是语法自动补齐view-in-browser是快速在浏览器中打开live server实时网页刷新 1. HTML 文件基本结构 <html><head><title>第一个页面</title></head><body&g…

vuedevtools图标不亮不能使用,显示vue.js not detected

&#xff08;1&#xff09;不亮解决&#xff1a; 根本原因就是下载的vue开发者工具不对&#xff0c;没有编译。 直接来一个最彻底的解决办法&#xff1a; 下载我已经编译好的shellchrome 链接: https://pan.baidu.com/s/1zKEgGxT5uAvofpD-T1Oa_w?pwd72m5 提取码: 72m5 解…

王者荣耀防御塔如何开发!新手小白做游戏开发采坑经过。phaser前端游戏框架

好嘞&#xff0c;游戏开发框架是js 开发的网页小游戏&#xff01; phaser这个框架。好我们先上图&#xff01; 目前大概是这么一个样子。 然后防御塔功能呢。简单的说就是当人物进去的时候打他。人物扣血。 我们的小人物是这样的代码 遇到的问题如下&#xff1b; 小白刚开始…

【Spring Security系列】Spring Security整合JWT:构建安全的Web应用

前言 在企业级开发或者我们自己的课程设计中&#xff0c;确保用户数据的安全性和访问控制非常重要。而Spring Security和JWT是都两个强大的工具&#xff0c;它俩结合可以帮助我们实现这一目标。 Spring Security提供了全面的安全功能&#xff0c;而JWT则是一种用于身份验证的…

最新win11配置cuda以及cudnn补丁教程

1、首先使用指令 nvidia-smi 查看电脑支持的**最高cuda**版本&#xff0c;例如&#xff1a;本机 12.2 2、进入CUDA下载cuda安装包 https://developer.nvidia.com/cuda-toolkit-archive 2、点击上方绿色的链接&#xff0c;按照图中序号选择的即可&#xff0c;最后点击下载。 …