单例模式
单例模式,算是最常见的设计模式了吧,他很简单,就是确保一个类只有一个实例。常用于保存一些全局状态信息。
下面是来自wikipedia的描述:
单例模式,也叫单子模式,是一种常用的软件设计模式,属于创建型模式的一种。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。
Golang实现
懒汉模式
所谓懒汉模式,就是指对象在需要的时候才进行创建,为什么叫懒汉模式,因为他很懒,所以他不会在不使用这个对象的时候进行创建,而是等到要使用的时候才去创建对象
不加锁实现
package singleton
type Singleton struct{}
var lazySingleton *Singleton
func GetInstance() *Singleton {
if lazySingleton == nil {
lazySingleton = new(Singleton)
}
return lazySingleton
}
对于不加锁实现,可能存在线程安全问题,在高并发的情况下,多个线程同时调用 GetInstance()
方法,都会检测到 lazySingleton
为 nil
,因此会创建多个对象。
加锁实现(双重检测)
使用Lock和Unlock,通过加锁操作,在检测到 lazySingleton
为 nil
时,加锁,同时再次检测,若为空,则创建对象,这样就解决了线程安全问题
package singleton
import "sync"
type Singleton struct{}
var lazySingleton *Singleton
var lock sync.Mutex
func GetInstance() *Singleton {
if lazySingleton == nil {
lock.Lock()
if lazySingleton == nil {
lazySingleton = new(Singleton)
}
lock.Unlock()
}
return lazySingleton
}
在Golang中,这种操作有着更加优雅的实现,即使用 once.Do()
package singleton
import "sync"
type Singleton struct{}
var lazySingleton *Singleton
var once = &sync.Once{}
func GetInstance() *Singleton {
if lazySingleton == nil {
once.Do(func() {
lazySingleton = new(Singleton)
})
}
return lazySingleton
}
饿汉模式
所谓饿汉模式,指的是在一开始就创建实例,而非等到使用时才创建,为何要叫饿汉模式,因为他饿,所以着急吃饭,所以就不能等到要用了才创建,必须在用之前就要创建实例。
饿汉模式的实现比较简单,只需要在 init()
函数里面创建实例即可
package singleton
type Singleton struct{}
var hungrySingleton *Singleton
func init() {
hungrySingleton = new(Singleton)
}
func GetInstance() *Singleton {
return hungrySingleton
}