1. Co to jest wzorzec Singleton
Wzorzec Singleton to wzorzec projektowy kreacyjny, który zapewnia, że klasa ma tylko jedną instancję i udostępnia globalny punkt dostępu do tej instancji celem pobrania. Wzorzec Singleton jest powszechnie stosowany w scenariuszach, gdzie zasoby muszą być dzielone, lub dostęp do konkretnej instancji musi być kontrolowany.
2. Charakterystyka i Zalety wzorca Singleton
Wzorzec Singleton ma następujące cechy i zalety:
- Zapewnia, że klasa ma tylko jedną instancję obiektu
- Udostępnia globalny punkt dostępu dla zewnętrznego kodu do pobrania instancji
- Unika powtarzającego się tworzenia instancji, co oszczędza zasoby systemu
3. Zastosowania wzorca Singleton
Wzorzec Singleton jest odpowiedni dla następujących scenariuszy zastosowań:
- Rejestratory: Zapewnienie, że istnieje tylko jeden rejestrator dla całego systemu, aby zapobiec duplikacji logowania.
- Pula połączeń do bazy danych: W środowiskach o dużej współbieżności, użycie wzorca Singleton może uniknąć częstego tworzenia i usuwania połączeń do bazy danych.
4. Implementacja wzorca Singleton w języku Golang
W języku Golang istnieją różne metody implementacji wzorca Singleton. Poniżej przedstawione są dwie powszechne metody implementacji.
4.1. Implementacja przy użyciu Leniwej Inicjalizacji i Wczesnej Inicjalizacji
Leniwa inicjalizacja tworzy obiekt instancji po raz pierwszy, gdy jest używany, podczas gdy wczesna inicjalizacja tworzy obiekt instancji przy starcie programu.
// Implementacja wzorca Singleton za pomocą leniwej inicjalizacji
package singleton
type Singleton struct {
}
var instance *Singleton
func GetInstance() *Singleton {
if instance == nil {
instance = &Singleton{}
}
return instance
}
// Implementacja wzorca Singleton za pomocą wczesnej inicjalizacji
package singleton
type Singleton struct {
}
var instance *Singleton = &Singleton{}
func GetInstance() *Singleton {
return instance
}
4.2. Problemy z Bezpieczeństwem Wątków w Wzorcu Singleton
Powyższa metoda leniwej inicjalizacji może mieć problemy w środowisku wielowątkowym, ponieważ kilka wątków może jednocześnie wejść do warunku if instance == nil
, co prowadzi do tworzenia wielu instancji.
4.3. Implementacja Wielowątkowej wersji wzorca Singleton za pomocą sync.Once
Użycie sync.Once
zapewnia, że tylko jedna gorutyna wykonuje kod inicjalizacyjny, rozwiązując w ten sposób problem z bezpieczeństwem wątków.
// Implementacja wielowątkowej wersji wzorca Singleton za pomocą sync.Once
package singleton
import (
"sync"
)
type Singleton struct {
}
var instance *Singleton
var once sync.Once
func GetInstance() *Singleton {
once.Do(func() {
instance = &Singleton{}
})
return instance
}
4.4. Implementacja Leniwej Inicjalizacji Wielowątkowej Wersji wzorca Singleton za pomocą sync.Mutex
Innym sposobem implementacji leniwej inicjalizacji wielowątkowej wersji wzorca Singleton jest użycie sync.Mutex
, aby zablokować i zapewnić, że tylko jedna gorutyna wykonuje operację inicjalizacji.
// Implementacja leniwej inicjalizacji wielowątkowej wersji wzorca Singleton za pomocą sync.Mutex
package singleton
import (
"sync"
)
type Singleton struct {
}
var instance *Singleton
var mu sync.Mutex
func GetInstance() *Singleton {
if instance == nil {
mu.Lock()
defer mu.Unlock()
if instance == nil {
instance = &Singleton{}
}
}
return instance
}