一、理论知识
单例设计模式(Singleton Design Pattern)是指一个对象只允许被实例化一次,并提供一个访问该实例的全局访问点。
应用场景:
- 避免资源访问冲突,例如写日志文件操作;
- 表示业务概念上的全局唯一类,例如ID生成器、配置信息、连接池类等;
优点:
- 减少了内存开销,尤其是频繁地创建和销毁实例时
- 避免对资源的重复占用,例如文件操作
缺点:
- 对OOP特性不友好
- 以id生成器为例,如果采用了单例模式,就违背了基于接口而非实现的设计原则,也就违背了广义上的抽象特性,如果某一天需要替换id生成器时,成本很大。
- 单例会隐藏类之间的依赖关系
- 单例类不需要显示创建、不需要依赖参数传递,如果代码关系复杂时,调用关系会被隐藏得很隐蔽。
- 单例对代码拓展性不友好
- 单例模式模式只能有一个对象实例,如果某一天需要在代码中创建两个或多个实例,改动代价就特别大。例如如果采用了单例连接池,后续需要改造成两个连接池,一个普通sql、一个慢sql。
二、代码实现
package a_singleton
import "sync"
type Singleton struct{}
var ins *Singleton
// GetInstanceLazy 懒汉式。非并发安全。
func GetInstanceLazy() *Singleton {
if ins == nil {
ins = &Singleton{}
}
return ins
}
// GetInstanceLazyWithLock 懒汉式加锁,并发安全,但是性能差
var mu sync.Mutex
func GetInstanceLazyWithLock() *Singleton {
mu.Lock()
defer mu.Unlock()
if ins == nil {
ins = &Singleton{}
}
return ins
}
// GetInstanceLazyWithDoubleCheck 懒汉式-双重检查。并发安全,性能ok。
// Java版该实现存在CPU指令重排序问题,需要volatile关键字禁止指令重排序
func GetInstanceLazyWithDoubleCheck() *Singleton {
if ins == nil {
mu.Lock()
defer mu.Unlock()
if ins == nil {
ins = &Singleton{}
}
}
return ins
}
// GetInstanceHungry 饿汉式
var insHungry *Singleton = &Singleton{}
func GetInstanceHungry() *Singleton {
return insHungry
}
// GetInstanceOnce 利用go自带并发工具sync.Once
var once sync.Once
func GetInstanceOnce() *Singleton {
once.Do(func() {
ins = &Singleton{}
})
return ins
}
标签:Singleton,return,语言,单例,ins,mu,func,go
From: https://www.cnblogs.com/csh24/p/17094134.html