mirror of
https://github.com/crazybber/go-pattern-examples.git
synced 2024-11-22 11:56: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"
|
||||
|
||||
//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
|
||||
|
||||
//GetInstance 用于获取单例模式对象
|
||||
func GetInstance() *Singleton {
|
||||
//GetWorkerInstance 总是获取到同一个Worker对象(内存位置相同)
|
||||
func GetWorkerInstance() *Worker {
|
||||
|
||||
//be sure ,to do this,only once!
|
||||
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"
|
||||
)
|
||||
|
||||
const parCount = 100
|
||||
const workerCount = 500
|
||||
|
||||
func TestSingleton(t *testing.T) {
|
||||
ins1 := GetInstance()
|
||||
ins2 := GetInstance()
|
||||
func TestWorkerSingleton(t *testing.T) {
|
||||
ins1 := GetWorkerInstance()
|
||||
ins2 := GetWorkerInstance()
|
||||
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.Add(parCount)
|
||||
instances := [parCount]*Singleton{}
|
||||
for i := 0; i < parCount; i++ {
|
||||
wg.Add(workerCount)
|
||||
instances := [workerCount]*Worker{}
|
||||
for i := 0; i < workerCount; i++ {
|
||||
go func(index int) {
|
||||
instances[index] = GetInstance()
|
||||
instances[index] = GetWorkerInstance()
|
||||
wg.Done()
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
for i := 1; i < parCount; i++ {
|
||||
for i := 1; i < workerCount; i++ {
|
||||
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