mirror of
https://github.com/crazybber/go-pattern-examples.git
synced 2024-11-26 05:36:03 +03:00
finish Singleton pattern
This commit is contained in:
parent
1b7e2c91c5
commit
7af536b222
@ -1,3 +1,9 @@
|
|||||||
# 单例模式
|
# 单例模式
|
||||||
|
|
||||||
使用懒惰模式的单例模式,使用双重检查加锁保证线程安全
|
大名鼎鼎的单例模式,永远返回相同内存位置的绝对的、同一个实例对象。
|
||||||
|
|
||||||
|
Go有两种常见的单例模式:
|
||||||
|
|
||||||
|
+ 使用懒惰模式的单例模式,使用`once.Do()`的双重同步检查保证线程安全生成单实例
|
||||||
|
|
||||||
|
+ 使用初始化的`init(){}`能力保证只生成一个实例
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user