【设计模式】创建型模式之单例模式(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 *Singleton

func GetInstance() *Singleton {
	if singleton == nil {
		singleton = &Singleton{}
	}
	return singleton
}

给方法加锁

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

package singleton

import "sync"

// 单例模式 懒汉式实现 方法锁
type Singleton struct{}

var singleton *Singleton
var mu sync.Mutex

func GetInstance() *Singleton {
	mu.Lock()
	defer mu.Unlock()
	if singleton == nil {
		singleton = &Singleton{}
	}
	return singleton
}

双重检测

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

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

package singleton

import "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 singleton

import "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单例模式

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

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

相关文章

vscode配置与注意事项

中文设置 https://zhuanlan.zhihu.com/p/263036716 应用搜索输入“Chinese (Simplified) Language Pack for Visual Studio Code”并敲回车键 底部信息窗没有的话 首先使用快捷键ctrlshiftp,Mac用户使shiftcommandp,然后输入settings.json 将下面的选…

C++其他语法总结

目录 《C基础语法总结》《C面向对象语法总结(一)》《C面向对象语法总结(二)》《C面向对象语法总结(三)》 一、运算符重载 运算符重载可以为运算符增加一些新的功能全局函数、成员函数都支持运算符重载常用的运算符重载示例 class Point {…

【前端素材】bootstrap5实现绿色果蔬电商Frutin

一、需求分析 绿色果蔬电商网站是指专门提供绿色、有机、天然果蔬产品在线销售的电子商务平台。这类网站通常提供以下功能: 产品展示和搜索:网站上展示各种绿色果蔬产品的图片、描述、产地等信息。用户可以通过搜索功能查找特定的果蔬产品或根据分类浏览…

我的年度总结(大一程序员的自述)

呀哈喽,我是结衣。 我也来参加这个年度总结的话题咯,喜欢的话可以点个赞哦。 作为一个大一新生,我从1级的编程小白到了现在的2级编程小白。在7月份之前我可以说是完全不了解编程的一位新人,对应电脑的了解也就只会打游戏看电视和浏…

66、python - 代码仓库介绍

上一节,我们可以用自己手写的算法以及手动搭建的神经网络完成预测了,不知各位同学有没有自己尝试来预测一只猫或者一只狗,看看准确度如何? 本节应一位同学的建议,来介绍下 python 代码仓库的目录结构,以及每一部分是做什么? 我们这个小课的代码实战仓库链接为:cv_lea…

安达发|APS排程系统之产品工艺约束

在制造业中,生产计划和排程是至关重要的环节。为了提高生产效率、降低成本并满足客户需求,企业需要采用先进的生产计划和排程系统。APS(Advanced Planning and Scheduling,高级计划与排程)系统是一种集成了多种先进技术…

设计模式-规格模式

设计模式专栏 模式介绍模式特点应用场景规格模式和策略模式的区别和联系代码示例Java实现规格模式Python实现规格模式 规格模式在spring中的应用 模式介绍 规格模式(Specification Pattern)是一种行为设计模式,其目的是将业务规则封装成可重…

[后端] 微服务的前世今生

微服务的前世今生 整体脉络: 单体 -> 垂直划分 -> SOA -> micro service 微服务 -> services mesh服务网格 -> future 文章目录 微服务的前世今生单一应用架构特征优点:缺点: 垂直应用架构特征优点缺点 SOA 面向服务架构特征优点缺点 微服…

2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷④

2023年全国职业院校技能大赛(高职组) “云计算应用”赛项赛卷4 目录 需要竞赛软件包环境以及备赛资源可私信博主!!! 2023年全国职业院校技能大赛(高职组) “云计算应用”赛项赛卷4 模块一 …

Every Nobody Is Somebody 「每小人物都能成大事」

周星驰 NFT Nobody即将发售,Nobody共创平台 Every Nobody Is Somebody Nobody 关于Nobody:Nobody是一款Web3共创平台,旨在为创作者提供一个交流和合作的场所,促进创意的产生和共享。通过该平台,创作者可以展示自己的作…

在群晖NAS上搭建私有部署笔记软件——Blossom

一、Blossom 简介 Blossom 是一个需要私有部署的笔记软件,虽然本身定位是一个云端软件,但你仍然可以在本地部署,数据和图片都将保存在本地,不依赖任何的图床或者对象存储。 Blossom | Blossom (wangyunf.com)https://www.wangyun…

【教学类-45-01】X-Y之间的“三连加“题(a+b+c=)

作品展示: 背景需求: 我常去的大4班孩子们基本都适应了0-5之间的加法题,做题速度极快。 为了增加“花样”,吸引幼儿参与,修改参数,从二连加12变为三连加111。 素材准备: 代码重点 代码展示 X-Y 之间的3…

备战2024美赛数学建模,文末获取历史优秀论文

总说(历年美赛优秀论文可获取) 数模的题型千变万化,我今天想讲的主要是一些「画图」、「建模」、「写作」和「论文结构」的思路,这些往往是美赛阅卷官最看重的点,突破了这些点,才能真正让你的美赛论文更上…

计算机图形学流体模拟 blender 渲染脚本

做流体模拟的时候,想要复现别人的成果,但是别人的代码都是每帧输出 ply 格式的文件,渲染部分需要自己完成 看了一下,似乎用 blender 是最简单的,于是记录一下过程中用到的代码 Blender 版本 4.0 批量导入 ply 假设…

Federated Unlearning for On-Device Recommendation

WSDM 2023 CCF-B Federated Unlearning for On-Device Recommendation 本文工作的主要介绍 本文主要介绍了一种名为FRU(Federated Recommendation Unlearning)的联邦学习框架,用于在设备端的推荐系统中实现用户数据的有效擦除和模型重建。…

专业课128分总分400+南京理工大学818信号系统与数字电路南理工考研经验分享

专业课128分总分400南京理工大学818信号系统与数字电路南理工电光院考研经验分享,希望自己的经历对大家有借鉴。 我是在六月底确认自己保不上研然后专心备考的,时间确实比较紧张。虽然之前暑假看了一点高数,但因为抱有保研的期望&#xff0c…

JMeter之Windows安装

JMeter之Windows安装 一、安装JDK二、安装JMeter1、下载JMeter2、配置环境变量3、验证JMeter 三、扩展知识1、汉化 一、安装JDK 略 二、安装JMeter 1、下载JMeter 官网地址:https://jmeter.apache.org/download_jmeter.cgi 放到本地目录下 2、配置环境变量 变量…

探索浏览器的内心世界:渲染机制的奥秘

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

im6ull学习总结(三-4)freetype显示单个字体

矢量字体引入 使用点阵字库显示英文字母、汉字时,大小固定,如果放大缩小则会模糊甚至有锯齿出现,为了解决这个问题,引用矢量字体。 矢量字体形成分三步: 第1步 确定关键点, 第2步 使用数学曲线&#xff08…

软件测试|Windows系统配置pytest+allure环境教程

前言 allure可以输出非常精美的测试报告,也可以和pytest进行完美结合,不仅可以渲染页面,还可以控制用例的执行。本文我们将介绍Windows系统中如何配置allure环境。 第一步:配置Java环境 因为allure的运行依赖于Java环境&#x…