finish Singleton pattern

This commit is contained in:
Edward 2020-04-23 09:47:58 +08:00
parent 1b7e2c91c5
commit 7af536b222
3 changed files with 87 additions and 20 deletions

View File

@ -1,3 +1,9 @@
# 单例模式 # 单例模式
使用懒惰模式的单例模式,使用双重检查加锁保证线程安全 大名鼎鼎的单例模式,永远返回相同内存位置的绝对的、同一个实例对象。
Go有两种常见的单例模式
+ 使用懒惰模式的单例模式,使用`once.Do()`的双重同步检查保证线程安全生成单实例
+ 使用初始化的`init(){}`能力保证只生成一个实例

View File

@ -2,17 +2,50 @@ package singleton
import "sync" import "sync"
//Singleton 是单例模式类 ////////////////////////////////
type Singleton struct{} //way 1
//使用 sync的 once.Do(){}确保执行一次
////////////////////////////////
var singleton *Singleton //Worker Singleton 是单例模式类
type Worker struct{}
//better to be pointer
var onlyTheWorker *Worker
// init a control
var once sync.Once var once sync.Once
//GetInstance 用于获取单例模式对象 //GetWorkerInstance 总是获取到同一个Worker对象(内存位置相同)
func GetInstance() *Singleton { func GetWorkerInstance() *Worker {
//be sure ,to do this,only once!
once.Do(func() { once.Do(func() {
singleton = &Singleton{} onlyTheWorker = &Worker{}
}) })
return singleton return onlyTheWorker
}
//Manager Singleton 是单例模式类
type Manager struct{}
//better to be pointer
var instance *Manager
//better to be pointer
var onlyTheManager *Manager
////////////////////////////////
//way2
//使用func init(){}函数来初始化保证,只初始化一次,更简单.
////////////////////////////////
func init() {
onlyTheManager = &Manager{}
}
//GetManagerInstance 总是获取到同一个Manager对象(内存位置相同)
func GetManagerInstance() *Manager {
return onlyTheManager
} }

View File

@ -5,30 +5,58 @@ import (
"testing" "testing"
) )
const parCount = 100 const workerCount = 500
func TestSingleton(t *testing.T) { func TestWorkerSingleton(t *testing.T) {
ins1 := GetInstance() ins1 := GetWorkerInstance()
ins2 := GetInstance() ins2 := GetWorkerInstance()
if ins1 != ins2 { if ins1 != ins2 {
t.Fatal("instance is not equal") t.Fatal("worker(instance) is not exactly the same")
} }
} }
func TestParallelSingleton(t *testing.T) { // 获取500次Worker 是否总是同一个worker
func TestParallelWorkerSingleton(t *testing.T) {
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
wg.Add(parCount) wg.Add(workerCount)
instances := [parCount]*Singleton{} instances := [workerCount]*Worker{}
for i := 0; i < parCount; i++ { for i := 0; i < workerCount; i++ {
go func(index int) { go func(index int) {
instances[index] = GetInstance() instances[index] = GetWorkerInstance()
wg.Done() wg.Done()
}(i) }(i)
} }
wg.Wait() wg.Wait()
for i := 1; i < parCount; i++ { for i := 1; i < workerCount; i++ {
if instances[i] != instances[i-1] { if instances[i] != instances[i-1] {
t.Fatal("instance is not equal") t.Fatal("Worker instance is not equal")
}
}
}
func TestManagerSingleton(t *testing.T) {
ins1 := GetManagerInstance()
ins2 := GetManagerInstance()
if ins1 != ins2 {
t.Fatal("Manager(instance) is not exactly the same")
}
}
// 获取500次Manager 是否总是同一个Manager
func TestParallelManagerSingleton(t *testing.T) {
wg := sync.WaitGroup{}
wg.Add(workerCount)
instances := [workerCount]*Manager{}
for i := 0; i < workerCount; i++ {
go func(index int) {
instances[index] = GetManagerInstance()
wg.Done()
}(i)
}
wg.Wait()
for i := 1; i < workerCount; i++ {
if instances[i] != instances[i-1] {
t.Fatal("Manager instance is not exactly equal")
} }
} }
} }