定义
单例设计模式(Singleton Design Pattern):在应用作用域中,类只允许创建一个实例(对象)
如何实现一个单例?
实现一个单例,需要关注下面几个要点:
- 构建函数需要是私有权限的,这样才能规避外部调用new创建实例;
- 考虑对象创建时的线程安全问题;
- 单例实例创建是否支持延迟加载
- 考虑getInstance()性能设计时候,根据应用场景考虑是否嵌入加锁
1. 饿汉式创建单例
饿汉式创建单例方式,在类初始化的时候,完成instance实例的创建并完成初始化,所以instance实例的创建过程是线程安全的.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
var inStance idGenerator
type idGenerator struct {
}
func init() {
rand.Seed(time.Now().UnixNano())
inStance = idGenerator{}
}
func GetInstance() idGenerator {
return inStance
}
func (id idGenerator) GetId() uint64 {
return rand.Uint64()
}
|
- 资源:如果实例占用资源多,提前初始化实例是浪费资源的行为。最好是等到程序需要用的时候再去初始化,按照fail-fast的设计原则(有问题早发现早处理),如果资源不够,在程序启动的时候就触发报错
- 耗时:如果存在初始化过程比较耗时,我们可以在程序启动的时候,将耗时初始化操作,提前放到程序启动的时候完成。
- 延迟加载:不支持
2. 懒汉式创建实例
懒汉式相较于饿汉式的创建实例的优势,在于支持延时加载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
var inStance *idGenerator
var m sync.Mutex
type idGenerator struct {
}
func GetInstance() *idGenerator {
if inStance == nil {
m.Lock()
if inStance == nil {
inStance = &idGenerator{}
}
m.Unlock()
}
return inStance
}
func (id idGenerator) GetId() uint64 {
return rand.Uint64()
}
|
思考:
- 如何理解单例模式中的唯一性?
- 如何实现线程唯一的单例?
- 如何实现集群环境下的单例?
- 如何实现一个多例模式?