Trong thế giới lập trình, đặc biệt là khi làm việc với Lập trình hướng đối tượng (OOP), chắc hẳn bạn đã nghe qua thuật ngữ “Singleton”. Đây là một trong những câu hỏi phỏng vấn kinh điển nhất cho các vị trí Developer. Vậy thực chất Singleton là gì? Tại sao nó vừa được yêu thích lại vừa bị xem là “Anti-pattern”?
Hãy cùng đi sâu vào tìm hiểu.
1. Singleton là gì?
Singleton (hay Singleton Pattern) là một mẫu thiết kế thuộc nhóm Creational Design Pattern (Mẫu khởi tạo).
Mục đích cốt lõi của Singleton là đảm bảo rằng một class (lớp) chỉ có duy nhất một instance (thể hiện) tồn tại trong suốt vòng đời của ứng dụng và cung cấp một điểm truy cập toàn cục (global access point) đến instance đó.
Hãy tưởng tượng Singleton giống như chức danh “Chủ tịch nước” của một quốc gia. Tại một thời điểm, chỉ có một người giữ chức vụ này và bất kỳ ai, ở đâu cũng đều biết người đó là ai.

Đặc điểm nhận dạng của một Singleton:
Để tạo ra một Singleton, class đó thường phải tuân thủ 3 nguyên tắc:
Private Constructor: Ngăn chặn việc tạo instance từ bên ngoài bằng từ khóa
new.Private Static Attribute: Biến tĩnh để lưu trữ instance duy nhất của class.
Public Static Method: Phương thức (thường đặt tên là
getInstance) để trả về instance đã được tạo.
2. Tại sao chúng ta cần dùng Singleton?
Không phải ngẫu nhiên mà Singleton trở nên phổ biến. Nó giải quyết hai vấn đề lớn:

Quản lý tài nguyên chia sẻ (Shared Resources): Có những tài nguyên mà việc tạo ra nhiều bản sao sẽ gây lãng phí bộ nhớ hoặc gây lỗi hệ thống. Ví dụ: Kết nối cơ sở dữ liệu (Database Connection), Logger, File Manager.
Truy cập toàn cục: Singleton cho phép bạn gọi đến đối tượng đó từ bất kỳ đâu trong dự án mà không cần truyền tham số qua lại giữa các hàm quá phức tạp.
3. Cách triển khai Singleton (Code ví dụ Java)
Có nhiều cách để viết Singleton, nhưng dưới đây là 2 cách phổ biến nhất:

Cách 1: Eager Initialization (Khởi tạo sớm)
Instance được tạo ngay khi class được load. Cách này đơn giản nhưng có thể gây lãng phí bộ nhớ nếu ứng dụng không bao giờ dùng đến instance đó.
public class EagerSingleton {
// Tạo instance ngay lập tức
private static final EagerSingleton instance = new EagerSingleton();
// Private constructor
private EagerSingleton() {}
public static EagerSingleton getInstance() {
return instance;
}
}Cách 2: Thread-Safe Lazy Initialization (Khởi tạo muộn an toàn)
Đây là cách “chuẩn chuyên gia” thường dùng. Instance chỉ được tạo khi cần thiết (Lazy) và đảm bảo hoạt động đúng trong môi trường đa luồng (Thread-safe) bằng kỹ thuật Double-Check Locking.
public class ThreadSafeSingleton {
private static volatile ThreadSafeSingleton instance;
private ThreadSafeSingleton() {}
public static ThreadSafeSingleton getInstance() {
// Check lần 1
if (instance == null) {
synchronized (ThreadSafeSingleton.class) {
// Check lần 2 để đảm bảo chỉ 1 thread được tạo
if (instance == null) {
instance = new ThreadSafeSingleton();
}
}
}
return instance;
}
}4. Khi nào nên sử dụng Singleton?
Bạn nên cân nhắc sử dụng Singleton trong các trường hợp thực tế sau:
Quản lý cấu hình (Configuration Service): Khi ứng dụng khởi động, nó đọc file config một lần và lưu vào Singleton để các module khác sử dụng.
Logging: Một hệ thống ghi log tập trung giúp tránh việc tranh chấp khi ghi vào cùng một file.
Caching: Lưu trữ dữ liệu tạm thời trong bộ nhớ để truy xuất nhanh.
Database Connection Pool: Quản lý các kết nối tới cơ sở dữ liệu để tránh việc đóng/mở kết nối liên tục gây chậm hệ thống.
5. Tranh cãi: Tại sao Singleton bị gọi là Anti-Pattern?
Mặc dù hữu ích, nhưng nhiều chuyên gia lập trình cao cấp (Senior/Architect) thường hạn chế dùng Singleton. Tại sao?
Cảnh báo: Việc lạm dụng Singleton có thể biến code của bạn thành “ác mộng” khi bảo trì.
Khó Unit Test: Singleton giữ trạng thái toàn cục (Global State), khiến việc viết Unit Test độc lập trở nên cực kỳ khó khăn vì các test case có thể ảnh hưởng lẫn nhau.
Vi phạm nguyên tắc Single Responsibility: Singleton vừa lo việc quản lý logic nghiệp vụ, vừa lo việc quản lý vòng đời của chính nó.
Ẩn giấu sự phụ thuộc (Hidden Dependencies): Khi nhìn vào constructor của một class khác, bạn không biết nó có đang gọi ngầm một Singleton nào đó bên trong hay không.
Giải pháp thay thế: Ngày nay, các Framework hiện đại như Spring Boot (Java) hay Angular sử dụng cơ chế Dependency Injection (DI) để quản lý các instance dạng Singleton một cách linh hoạt hơn mà không cần fix cứng code theo Singleton Pattern truyền thống.
Xem thêm:
Rest Assured là gì? Giải mã từ A-Z dưới góc nhìn chuyên gia công nghệ
Redux Saga là gì? Giải mã “Phù thủy” xử lý Side Effect trong Redux
Tổng kết
Hiểu rõ Singleton là gì là bước đầu tiên để bạn làm chủ các Design Pattern.
Nên dùng: Khi bạn cần kiểm soát chặt chẽ một tài nguyên duy nhất (như DB connection, Config).
Tránh dùng: Khi bạn muốn code dễ test, dễ mở rộng và tránh các lỗi về Global State.
Hy vọng bài viết này đã giúp bạn có cái nhìn toàn diện về Singleton. Chúc các bạn áp dụng thành công vào dự án của mình!

Công nghệ tương lai Lập trình/ Code
Portainer Là Gì? Toàn Tập Về Công Cụ Quản Trị Container Hàng Đầu (Hướng Dẫn Chi Tiết)
Sự bùng nổ của công nghệ Container hóa (Containerization) với đầu tàu là Docker
Xem thêmTh3
Công nghệ tương lai Công cụ và hướng dẫn Lập trình/ Code
Helper Là Gì? Bí Quyết Viết Code “Sạch” Và Tối Ưu Trong Lập Trình
Trong thế giới lập trình và phát triển phần mềm, việc phải lặp đi
Xem thêmTh3
Digital Maketing Đồ Họa và Video Xu hướng
Des là gì? Giải mã ý nghĩa của Des trong Thiết kế, SEO, IT & Logistics
Bạn đang lướt mạng xã hội và thấy ai đó bình luận: “Dân Des
Xem thêmTh3