(Post 28/03/2006) Singleton Pattern là pattern
đảm bảo rằng một lớp chỉ có một thể hiện (instance) duy nhất và trong
đó cung cấp một cổng giao tiếp chung nhất để truy cập vào lớp đó.
Singleton Pattern: “Ensure a class only has one instance,
and provide a global point of access to it.” [GoF]
1. Định nghĩa
Singleton Pattern là pattern đảm bảo rằng một lớp chỉ
có một thể hiện (instance) duy nhất và trong đó cung cấp một cổng giao
tiếp chung nhất để truy cập vào lớp đó.
Hộp thoại
Find, một ví dụ cụ thể cho Singleton Pattern chỉ một hộp thoại
duy nhất xuất hiện dù chọn menu nhiều lần |
|
Một số ví dụ về Singleton Pattern: file system, file
manager, window manager, printer spooler, ngày giờ…
2. Lợi ích
Việc sử dụng Singleton Pattern đem lại các lợi ích sau:
- Quản lý việc truy cập tốt hơn vì chỉ có một thể hiện đơn nhất.
- Cho phép cải tiến lại các tác vụ (operations) và các thể hiện (representation)
do pattern có thể được kế thừa và tùy biến lại thông qua một thể hiện
của lớp con
- Quản lý số lượng thể hiện của một lớp, không nhất thiết chỉ có một
thể hiện mà có số thể hiện xác định.
- Khả chuyển hơn so với việc dùng một lớp có thuộc tính là static,
vì việc dùng lớp static chỉ có thể sử dụng một thể hiện duy nhất,
còn Singleton Pattern cho phép quản lý các thể hiện tốt hơn và tùy
biến theo điều kiện cụ thể.
3. Trường hợp sử dụng
Người lập trình có thể dùng Singleton Pattern trong những
trường hợp sau:
- Trong trường hợp chỉ cần một thể hiện duy nhất của một lớp.
- Khi thể hiện duy nhất khả mở thông qua việc kế thừa, người dùng
có thể sử dụng thể hiện kế thừa đó mà không cần thay đổi các đoạn
mã của chương trình.
4. Cách thực hiện
Thực hiện Singleton Pattern theo các bước sau:
- Định nghĩa một thuộc tính private và static
trong lớp Singleton: instance.
- Định nghĩa tất cả các constructor thành protected
hoặc private để người dùng không thể tạo thực thể
trực tiếp từ lớp.
- Định nghĩa một accessor public và static
trong lớp: getInstance().
- Thực hiện "lazy initialization" (khởi tạo chậm, khởi tạo
khi yêu cầu) trong getInstance(): trả về một thể
hiện mới hay một giá trị rỗng (null) tùy thuộc vào
một biến boolean, biến này như một cờ hiệu dùng báo xem lớp đó đã
có thể hiện hay chưa.
- Clients chỉ dùng getInstance() để tạo đối tượng
của lớp Singleton.
- Thừa kế cũng được hỗ trợ, nhưng không che (overridden) các phương
thức static: lớp cơ sở phải được khai báo là friend
với lớp dẫn xuất (để truy xuất đến protected constructor).
Trong chế độ đa luồng (multithreading), Singleton Pattern
có thể làm việc không tốt: hai thread có thể gọi phương thức sinh đối
tượng cùng thời điểm và hai thể hiện sẽ được tạo ra.
Có nhiều giải pháp: double-checked locking1
, class loader (Java). Ví dụ dùng class loader:
1 Khai báo volatile
cho instance trong Java, C# để tránh lớp làm việc không
chính xác do quá trình tối ưu của trình biên dịch.
5. Các pattern liên quan
- Abstract Factory: thường dùng để trả về các đối tượng duy nhất.
- Builder: dùng tạo một đối tượng phức tạp, trong đó Singleton được
dùng để tạo một đối tượng truy xuất tổng quát.
- Prototype: dùng để sao chép một đối tượng, hoặc tạo ra một đối tượng
khác từ prototype (nguyên mẫu) của nó, trong đó Singleton được dùng
để chắc chắn chỉ có một prototype.
6. Ví dụ minh họa
a) Java
Chú ý các chú thích trong chương trình kiểm tra: cột
trái là các số xuất hiện khi dùng Singleton (chỉ có một thể hiện duy nhất
của lớp), cột phải là các số xuất hiện khi không dùng Singleton (có hai
thể hiện của lớp).
b) C++
c) C#
Phiên bản C# có hỗ trợ đa luồng (multithreading), dùng
phương pháp “double checked locking”.
Dương Thiên Tứ
Faculty FPT-Aptech
|