Mẫu Singleton thuộc nhóm mẫu thiết kế sáng tạo (creational pattern), đảm bảo một lớp chỉ tồn tại duy nhất một thể hiện trong toàn bộ hệ thống. Cơ chế này cung cấp điểm truy cập toàn cục đến thể hiện đó, giải quyết bài toán quản lý tài nguyên chia sẻ như kết nối cơ sở dữ liệu hoặc cấu hình ứng dụng.
Đặc điểm cốt lõi của mẫu này bao gồm:
- Constructor được khai báo
privateđể ngăn việc khởi tạo từ bên ngoài - Biến lưu trữ thể hiện được đánh dấu
static - Phương thức truy cập toàn cục trả về thể hiện duy nhất
Triển khai cơ bản với khởi tạo tức thì (eager initialization):
public class SingleInstance {
private static final SingleInstance uniqueRef = new SingleInstance();
private SingleInstance() {}
public static SingleInstance getReference() {
return uniqueRef;
}
}
Cách tiếp cận này tạo thể hiện ngay khi lớp được nạp vào JVM, phù hợp khi tài nguyên không tốn kém và ứng dụng luôn sử dụng đối tượng. Ưu điểm là đảm bảo an toàn đa luồng tự nhiên do khởi tạo trước khi chạy ứng dụng.
Đối với khởi tạo trì hoãn (lazy initialization) trong môi trường đa luồng:
public class SingleInstance {
private static volatile SingleInstance uniqueRef;
private SingleInstance() {}
public static SingleInstance getReference() {
if (uniqueRef == null) {
synchronized (SingleInstance.class) {
if (uniqueRef == null) {
uniqueRef = new SingleInstance();
}
}
}
return uniqueRef;
}
}
Cơ chế double-checked locking ở trên kết hợp từ khóa volatile để ngăn tối ưu hóa bộ biên dịch gây lỗi khi truy cập đồng thời. Biến uniqueRef được khởi tạo chỉ khi thực sự cần, đồng thời đảm bảo tính nguyên tử trong môi trường đa luồng.
Mẫu Singleton giúp tối ưu tài nguyên bằng cách loại bỏ việc tạo nhiều thể hiện không cần thiết. Tuy nhiên, cần cân nhắc kỹ khi áp dụng vì có thể dẫn đến phụ thuộc ngầm và gây khó khăn trong kiểm thử đơn vị. Việc sử dụng nên tập trung vào các trường hợp quản lý tài nguyên hệ thống có trạng thái toàn cục.