1. Singleton Pattern là gì
Singleton Pattern là một mẫu thiết kế khởi tạo đảm bảo rằng một lớp chỉ có một thể hiện và cung cấp một điểm truy cập toàn cục đến thể hiện đó để lấy. Mẫu singleton thường được sử dụng trong các tình huống mà tài nguyên cần được chia sẻ hoặc truy cập vào một thể hiện cụ thể cần được kiểm soát.
2. Đặc điểm và Ưu điểm của Singleton Pattern
Singleton Pattern có những đặc điểm và ưu điểm sau:
- Đảm bảo rằng lớp chỉ có một thể hiện đối tượng
- Cung cấp một điểm truy cập toàn cục để mã bên ngoài có thể lấy thể hiện đó
- Tránh việc tạo thể hiện lặp đi lặp lại, tiết kiệm tài nguyên hệ thống
3. Các Tình huống Ứng dụng của Singleton Pattern
Singleton Pattern phù hợp cho các tình huống ứng dụng sau:
- Loggers: Đảm bảo chỉ có một logger cho toàn bộ hệ thống để ngăn chặn việc đăng nhập trùng lặp.
- Database Connection Pool: Trong môi trường cao cấp độ cộng lồn, sử dụng Singleton Pattern có thể tránh việc tạo và hủy kết nối cơ sở dữ liệu thường xuyên.
4. Triển khai Singleton Pattern trong Golang
Trong Golang, có các cách triển khai Singleton Pattern khác nhau. Dưới đây là hai phương pháp triển khai phổ biến.
4.1. Triển khai sử dụng Khởi tạo Lười biếng và Khởi tạo Nhanh chóng
Khởi tạo lười biếng tạo thể hiện đối tượng khi nó được sử dụng lần đầu tiên, trong khi khởi tạo nhanh chóng tạo thể hiện đối tượng khi chương trình bắt đầu.
// Triển khai Singleton Pattern sử dụng khởi tạo lười biếng
package singleton
type Singleton struct {
}
var instance *Singleton
func GetInstance() *Singleton {
if instance == nil {
instance = &Singleton{}
}
return instance
}
// Triển khai Singleton Pattern sử dụng khởi tạo nhanh chóng
package singleton
type Singleton struct {
}
var instance *Singleton = &Singleton{}
func GetInstance() *Singleton {
return instance
}
4.2. Vấn đề An toàn Luồng trong Singleton Pattern
Phương pháp triển khai khởi tạo lười biếng ở trên có thể gặp vấn đề trong môi trường đa luồng vì nhiều luồng có thể đồng thời điều kiện if instance == nil
, dẫn đến việc tạo ra nhiều thể hiện.
4.3. Triển khai Singleton Pattern An toàn Luồng sử dụng sync.Once
Sử dụng sync.Once
đảm bảo rằng chỉ một goroutine thực thi mã khởi tạo, từ đó giải quyết vấn đề an toàn luồng.
// Triển khai Singleton Pattern an toàn luồng sử dụng 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. Triển khai Singleton Pattern Khởi tạo Lười biếng An toàn Luồng sử dụng sync.Mutex
Một cách khác để triển khai Singleton Pattern khởi tạo lười biếng an toàn luồng là sử dụng sync.Mutex
để khóa và đảm bảo chỉ một goroutine thực thi hoạt động khởi tạo.
// Triển khai Singleton Pattern khởi tạo lười biếng an toàn luồng sử dụng 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
}