From 7af536b2225692a603a97124b2279baea0b4babd Mon Sep 17 00:00:00 2001 From: Edward Date: Thu, 23 Apr 2020 09:47:58 +0800 Subject: [PATCH] finish Singleton pattern --- creation/03_singleton/README.md | 8 +++- creation/03_singleton/singleton.go | 47 ++++++++++++++++++---- creation/03_singleton/singleton_test.go | 52 +++++++++++++++++++------ 3 files changed, 87 insertions(+), 20 deletions(-) diff --git a/creation/03_singleton/README.md b/creation/03_singleton/README.md index 8bf5720..6b6ac50 100644 --- a/creation/03_singleton/README.md +++ b/creation/03_singleton/README.md @@ -1,3 +1,9 @@ # 单例模式 -使用懒惰模式的单例模式,使用双重检查加锁保证线程安全 +大名鼎鼎的单例模式,永远返回相同内存位置的绝对的、同一个实例对象。 + +Go有两种常见的单例模式: + ++ 使用懒惰模式的单例模式,使用`once.Do()`的双重同步检查保证线程安全生成单实例 + ++ 使用初始化的`init(){}`能力保证只生成一个实例 diff --git a/creation/03_singleton/singleton.go b/creation/03_singleton/singleton.go index c99a380..bd644f1 100644 --- a/creation/03_singleton/singleton.go +++ b/creation/03_singleton/singleton.go @@ -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 } diff --git a/creation/03_singleton/singleton_test.go b/creation/03_singleton/singleton_test.go index ad7928e..76dc2b8 100644 --- a/creation/03_singleton/singleton_test.go +++ b/creation/03_singleton/singleton_test.go @@ -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") } } }