Mẫu thiết kế Singleton: Định nghĩa và vị trí
Mẫu thiết kế Singleton là một trong những mẫu thiết kế thuộc nhóm creational, được phát triển nhằm đảm bảo rằng một lớp chỉ có một instance duy nhất trong toàn bộ ứng dụng. Điều này giúp tiết kiệm bộ nhớ và tối ưu hóa hiệu suất, tránh việc khởi tạo nhiều đối tượng không cần thiết.
Giống như việc mỗi gia đình chỉ cần một ấm nước để sử dụng cho các nhu cầu khác nhau, Singleton cũng cung cấp một đối tượng dùng chung mà không cần phải khởi tạo lại mỗi khi cần sử dụng.
Mục tiêu của Singleton
Mẫu thiết kế Singleton có hai mục tiêu chính mà nó hướng tới:
- Tạo ra một đối tượng duy nhất: Điều này giúp giảm thiểu số lượng đối tượng được khởi tạo, tiết kiệm tài nguyên bộ nhớ và tối ưu hóa hiệu suất của ứng dụng.
- Cung cấp thông tin chia sẻ: Đối tượng này có thể được truy cập từ bất cứ đâu trong chương trình, điều này giúp đơn giản hóa việc quản lý dữ liệu và tiết kiệm thời gian truy xuất.
Sơ đồ lớp của Singleton
Để hiểu rõ hơn về cách hoạt động của Singleton, chúng ta có thể tham khảo sơ đồ lớp dưới đây:
- Lớp Singleton sẽ chứa một biến static để lưu trữ instance duy nhất của nó.
- Biến này là private và chỉ có thể được truy cập thông qua một hàm static có tên getInstance().
- Constructor của lớp này cần được định nghĩa là private để không thể khởi tạo từ bên ngoài lớp.
Ứng dụng của Singleton
Singleton thường được áp dụng cho những lớp tiêu tốn nhiều tài nguyên khi khởi tạo, như các kết nối đến cơ sở dữ liệu hoặc đối tượng Logger, khi mà mỗi lớp đó chỉ cần được khởi tạo một lần và sử dụng trong suốt thời gian chạy ứng dụng.
Thực hành với Singleton
Để giúp các bạn dễ hình dung, chúng ta sẽ thực hiện ba ví dụ cụ thể về mẫu thiết kế này:
1. Không sử dụng Singleton
dart
class ExampleWithoutSingleton { }
void main() {
var singleton1 = ExampleWithoutSingleton();
var singleton2 = ExampleWithoutSingleton();
print(identical(singleton1, singleton2)); // false
}
Kết quả sẽ là: false, cho thấy hai đối tượng không giống nhau.
2. Sử dụng Singleton theo lý thuyết
dart
class ExampleByTheory {
ExampleByTheory._internal();
static ExampleByTheory? _instance = ExampleByTheory._internal();
static ExampleByTheory getInstance() {
return _instance ?? ExampleByTheory._internal();
}
}
void main() {
var singleton1 = ExampleByTheory.getInstance();
var singleton2 = ExampleByTheory.getInstance();
print(identical(singleton1, singleton2)); // true
}
Kết quả sẽ là: true, chứng minh rằng cả hai tham chiếu đều trỏ đến cùng một instance.
3. Sử dụng Singleton một cách "pro" với Dart
dart
class ExampleByDartWay {
ExampleByDartWay._internal();
static ExampleByDartWay _instance = ExampleByDartWay._internal();
factory ExampleByDartWay() {
return _instance;
}
}
Sử dụng từ khóa factory trong Dart giúp cho việc quản lý việc khởi tạo instance trở nên dễ dàng hơn, không phải lo lắng về việc tạo ra nhiều đối tượng.
Kết hợp với Flutter
Trong các ứng dụng Flutter, mẫu Singleton có thể được áp dụng linh hoạt cho nhiều tình huống khác nhau như quản lý trạng thái, kết nối mạng, và các dịch vụ khác. Việc sử dụng các thư viện như provider, get_it, và riverpod đã giúp việc triển khai mẫu của Singleton trở nên dễ dàng hơn và hiệu quả hơn.
Kết luận
Chúng ta đã khám phá xong mẫu thiết kế Singleton. Ở phần tiếp theo của chuỗi bài viết, chúng ta sẽ tiếp tục tìm hiểu về mẫu thiết kế tiếp theo: Adapter - người hùng thầm lặng. Hãy cùng đón chờ nhé!
source: viblo