单例模式
概念
单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。
要点:
- 某个类只有一个实例。
- 保证自行创建这个实例。
- 向这个系统提供这个实例。
实现分析
基于单例模式的三个要点,代码实现中需要有一下保证:
- 禁止用户创建实例:私有化构造函数。
- 单例类提供一个公有方法,该方法负责确保实例存在,并将该实例提供给整个系统使用。
根据实例创建的时间可分为:懒汉模式、饿汉模式。
C++样例
饿汉模式
程序一开始就产生该类的实例。
class Singleton {
public:
static Singleton* getInstance();
private:
Singleton();
static Singleton* INSTANCE;
};
Singleton* Singleton::INSTANCE = new Singleton();
Singleton* Singleton::getInstance() {
return Singleton::INSTANCE;
}
懒汉模式
程序中第一次使用该类实例时才创建实例。
class Singleton {
public:
static Singleton* getInstance();
private:
Singleton();
static Lock; // 并发锁
static Singleton* INSTANCE;
};
Singleton* Singleton::INSTANCE = nullptr;
// 线程不安全版本
Singleton* Singleton::getInstance() {
if (INSTANCE == nullptr) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
// 线程安全版本
Singleton* Singleton::getInstance() {
if (INSTANCE == nullptr) {
// Lock 并发锁
if (INSTANCE == nullptr) {
INSTANCE = new Singleton();
}
// UnLock
}
return INSTANCE;
}
Go样例
饿汉模式
func init() {
// 饿汉模式
hInstance = &hungerSingleton{}
}
type hungerSingleton struct { }
var hInstance *hungerSingleton
func GetHungerInstance() *hungerSingleton {
return hInstance
}
懒汉模式
type lazySingleton struct { }
var instance *lazySingleton
var lock sync.Mutex
func GetLazyInstance() *lazySingleton {
if instance == nil { // 不是完全原子的
lock.Lock()
defer lock.Unlock()
if instance == nil {
instance = &lazySingleton{}
}
}
return instance
}
// 通过使用sync/atomic这个包,我们可以原子化加载并设置一个标志,以标识是否创建实例
var initialized uint32
func GetLazyInstanceAtom() *lazySingleton {
if atomic.LoadUint32(&initialized) == 1 {
return instance
}
lock.Lock()
defer lock.Unlock()
if instance == nil {
instance = &lazySingleton{}
atomic.StoreUint32(&initialized, 1)
}
return instance
}
// 通过 sync.Once 来确保创建实例的方法只执行一次
var initOnce sync.Once
func GetLazyInstanceOnce() *lazySingleton {
initOnce.Do(func() {
instance = &lazySingleton{}
})
return instance
}
参考:
- 《大话设计模式》 程杰
- [图说设计模式-单例模式](