Golang语言设计模式的实现—单例模式
一个类只允许创建一个对象,那么这个类就叫做一个单例类,这种设计模式就叫做单例设计模式。单例模式不仅有利于减少内存开支,还有减少系统性能开销、防止多个实例产生冲突等优点。
因为单例模式保证了实例的全局唯一性,而且只被初始化一次,所以比较适合全局共享一个实例,且只需要被初始化一次的场景 例如数据库实例、全局配置、全局任务池 要求生成唯一的序列号 缓存之类的数据,可以用单例缓存起来 创建一个对象需要消耗过多的资源时,比如文I/O与数据的连接等等
单例模式又分为饿汉方式和懒汉方式。饿汉方式指全局的单例实例在包被加载时创建,而懒汉方式指全局的单例实例在第一次被使用时创建,我们可以看到,这种命名方式非常形象地体现了它们不同的特点。
饿汉式:
package main import "fmt" // Singleton 保证一个类永远只能有一个对象,这个对象还能被系统的其他模块使用 type singleton struct{ } var instance *singleton = &singleton{ } func GetInstance() *singleton { return instance } func (s *singleton) SomeTing() { fmt.Println("单例中的某方法") }
懒汉式: 懒汉式在平时使用比较多,但是在并发环境中他是不安全的,需要进行加锁
package main import ( "fmt" "sync" "sync/atomic" ) // Singleton 保证一个类永远只能有一个对象,这个对象还能被系统的其他模块使用 type singleton struct{ } var instance *singleton // 定义一个锁 var lock sync.Mutex // 定义一个标记 var initialized uint32 func GetInstance() *singleton { if atomic.LoadUint32(&initialized) == 1 { return instance } lock.Lock() defer lock.Unlock() //只有首次GetInstance()方法被调用,才会生成这个单例的对象 if instance == nil { instance = &singleton{ } atomic.StoreUint32(&initialized, 1) return instance } return instance } func (s *singleton) SomeTing() { fmt.Println("单例中的某方法") }
除了懒汉式和饿汉式以外,在golang语言中有一种更加优雅的方法实现单例模式,使用once.Do可以确保 instance 实例全局只被创建一次,once.Do 函数还可以确保当同时有多个创建动作时,只有一个创建动作在被执行
package main import "sync" var once sync.Once type singleton struct{ } var instance *singleton func GetInstance() *singleton { //使用once.Do once.Do(func() { instance = &singleton{ } }) return instance }