单例模式是一种创建型设计模式,让你能够保证一个类只有一个实例,并提供一个访问该实例的全局节点。
实现单例模式需要一下两步:
- 将默认构造函数设为私有, 防止其他对象创建对象的实例。
- 新建一个静态构建方法作为构造函数,用于生成对象。此后所有对于该函数的调用都将返回这一缓存对象。
优点:
-
你可以保证一个类只有一个实例
-
你获得了一个指向该实例的全局访问节点
-
仅在首次请求单例对象时对其进行初始化
缺点:
- 违反了单一职责原则。 同时解决了两个问题:保证一个类只有一个实例 和 为该实例提供一个全局访问节点
- 单例模式可能掩盖不良设计, 比如程序各组件之间相互了解过多等
- 该模式在多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象
- 单例的客户端代码单元测试可能会比较困难, 因为许多测试框架以基于继承的方式创建模拟对象
实例代码:
package main
import (
"sync"
"sync/atomic"
)
type singleton struct {
num int32
}
var slton *singleton = nil
var mutex sync.Mutex
func getSingleton() *singleton {
if slton != nil {
return slton
}
mutex.Lock()
defer mutex.Unlock()
return &singleton{num: 0}
}
func (s *singleton) getNum() int32 {
return atomic.LoadInt32(&s.num)
}
func (s *singleton) setNum(num int32) int32 {
return atomic.SwapInt32(&s.num, num)
}
func main() {
ch := make(chan int32, 100)
var w sync.WaitGroup
for i := 0; i < 100; i++ {
w.Add(1)
go func(i int32) {
s := getSingleton()
s.setNum(i)
ch <- s.getNum()
if len(ch) == 100 {
close(ch)
}
w.Done()
}(int32(i))
}
w.Wait()
for _ = range ch { }
}