Singleton Pattern – Fundamental
Singleton có lẽ là một trong những pattern có tính trừu tượng dễ hiểu nhất mà người học design pattern nào cũng biết. Trong dự án vừa rồi tôi có phải implement một cái database connection pool và thread pool mà nó chính xác là một singleton object. Tôi đã chọn Singleton để implement những class đó. Tất nhiên singleton chỉ là một phần nhỏ, không phải phần cốt lõi trong những cái pool đó, nhưng trong bài viết này tôi sẽ viết về singleton pattern như là bài viết đầu tiên về loạt bài design pattern tiếp theo. Những bài viết của tôi thường lấy ý tưởng từ những quyển sách kinh điển (nhiều khi là dịch lại – vì họ viết quá xuất sắc và không có gì cần thêm hay bớt). Tôi chỉ cố gắng hiểu một cách sâu sắc nhất và ghi lại theo cách hiểu. Trong ví dụ về design pattern, tôi chọn quyển Gang Of Four – Design Patterns – Elements of Reusable Object-Oriented Sofware, một quyển sách kinh điển nhất về design pattern. Nếu bạn có thời gian thì hãy dành thời gian đọc nó (bằng tiếng Anh để hiểu sâu sắc hơn).
1. Mục đính và ý nghĩa.
- Đảm bảo rằng một class có duy nhất một thực thể (instance) hay đối tượng (object) và cung cấp một cách thức truy nhập toàn cục để có thể từ bất kỳ đâu cũng lấy được instance duy nhất đó. Chúng ta cũng gọi thực thể duy nhất đó là thực thể chính (solely) của class đó.
Đối với một vài class thì việc chỉ có duy nhất một instance (object) là rất quan trọng. Mặc dù có rất nhiều máy in trong hệ thống nhưng chỉ có một printer spooler. Cũng chỉ có một file system và một windows manager. Cũng như trong thiết kế connection pool thì chỉ có một connection pool quản lý nhiều connection.
Làm thế nào để chúng ta đảm bảo một class chỉ có một thể hiện duy nhất và dễ dàng truy nhập được? Một object toàn cục có thể làm cho nó dễ dàng truy nhập được nhưng không ngăn cấm bạn tạo thêm nhiều object khác.
Một giải pháp tốt hơn là làm cho class đó tự bản thân nó có thể điều khiển được thực thể chính của nó. Class đó có thể đảm bảo rằng không có thực thể khác được tạo ra (bằng cách chặn đứng các yêu cầu tạo object mới) và cung cấp cách thức để truy nhập được thực thể chính của nó. Đó là singleton pattern.
2. Cấu trúc
3. Implementation
Phương pháp chung nhất để đảm bảo có một thực thể duy nhất là giấu đi cách thức tạo ra thực thể ở bên trong lớp đó (hoặc là static member function hoặc một member function của class đó) và trong những hàm này thì đã đảm bảo rằng chỉ một thực thể được tạo ra. Có nghĩa là người sử dụng sẽ không thể gọi hàm constructor và destructor mà phải gọi thông qua một member function của lớp. Member function sẽ truy nhập vào biến mà lưu giữ thực thể duy nhất và đảm bảo rằng biến này được khởi tạo với thực thể duy nhất trước khi trả về giá trị. Cách tiếp cận này đảm bảo rằng singleton được tạo ra và khởi tạo trước khi nó được sử dụng lần đầu tiên. Bạn có thể định nghĩa hàm này trong C++ như một static member function Instance() của lớp Singleton. Singleton cũng định nghĩa biến static member variable _instance là con trỏ đến thực thể duy nhất.
class Singleton
{
public:
static Singleton* Instance();
protected:
Singleton();
private:
static Singleton* _instance;
};
Singleton* Singleton::_instance = 0;
Singleton* Singleton::Instance ()
{
if (_instance == 0) {
_instance = new Singleton;
}
return _instance;
}
Người sử dụng hoàn toàn truy nhập vào singleton thông qua member function Instance(). Biến _instance được khởi tạo là 0 và Instance() sẽ trả về giả trị của biến đó, khởi tạo nó bởi một thực thể duy nhất nếu nó là 0. Hàm này sử dụng cách thức khởi tạo lười biếng, nghĩa là thực thể không được tạo ra và lưu trữ cho đến khi nó lần đầu được truy nhập.
Chú ý rằng hàm constructor là protected. Người sử dụng cố gắng khởi tạo một thực thể mới Singleton trực tiếp (bằng constructor) sẽ gặp lỗi lúc biên dịch. Điều này đảm bảo rằng chỉ có một thực thể có thể được tạo ra.
Hơn thế nữa, vì _instance là pointer đến đối tượng Singleton, nên member function Instance() có thể gán con trỏ tới một subclass của Singleton vào biến _instance.
Dạo này nhàn nhỉ
Nhàn là nhàn thế nào? Tuần vừa rồi lúc nào cũng hơn 12 tiếng một ngày. Căn bản là phải quyết tâm chịu khó viết lách chút thôi :->
Đã đọc
Thực sự rất hay và rất dễ hiểu
Tiết kiệm được bao nhiêu thời gian đọc sách
Thanks Mr Hoàng Trần
Sao chưa thấy các bài tiếp theo của series nhỉ?
À cái “khởi tạo lười biếng” là thế nào ý nhỉ?
Khởi tạo lười biếng (Lazy initialization) là chúng ta tạm thời delay lại quá trình khởi tạo một object cho đến khi object đó thực sự được sử dụng. Ví dụ trong ví dụ trên, nếu chúng ta không gọi hàm Instance() để lấy instance để sử dụng thì chẳng lúc nào gọi new Instance để khởi tạo một object mới.
Lấy một ví dụ khác, chúng ta có một lớp Account gì đó rất phức tạp và để khởi tạo một object của nó chúng ta phải connect vào database và lấy thông tin về object đó (expensive). Nhưng đôi khi khởi tạo một object Account chúng ta chưa cần gì ngay đến các thông tin bên trong của nó, khi đó chúng ta sử dụng lazy initialization.
Xem thêm
http://en.wikipedia.org/wiki/Lazy_initialization
Riêng tư một chút thì trong PMS
có sử dụng cái này nhiều. Và cũng có một số singleton
Anh Hoang oi, em dang hoc design pattern, anh co cuon tai lieu: Gang Of Four – Design Patterns – Elements of Reusable Object-Oriented Sofware cho em xin voi duoc khong. Cam on anh nhieu
Email cua em: cuong_qh2002@yahoo.com
Giờ mình mới biết thiết kế và phân tính quan trọng nhiều hơn viết code, bạn có thể cho mình cuốn Design Patterns – Gang of Four chứ, có cuốn nào dịch ra tiếng việt mà dịch chuẩn chút bạn có thể gửi cho mình chứ, E-mail: five1412@yahoo.com. Mình cảm ơn bạn trước nhé….
“The only way to learn a new programming language is by writing programs in it” (Câu nói hay và ý nghĩa)
@Hùng:
Design Patterns là 1 kiến thức cực kì quan trọng cho các lập trình viên mà hình như các trường lớp ở VN rất ít nhắc tới
Nếu bạn muốn trở thành 1 programmer giỏi thì không thể không học design patterns. Tuy nhiên cuốn Design Patterns: Gang of Four đọc rất khó hiểu vì các tác giả viết quá cô đọng, theo kiểu sách tham khảo chứ không phải sách học cho người mới bắt đầu.
Nếu bạn mới bắt đầu làm quen với môn này thì mình khuyên bạn nên đọc cuốn Head First Design Patterns. Cuốn này viết rất dễ hiểu. Đọc cuốn này trước rồi tham khảo sang cuốn kia là cách học tốt nhất.
Cả 2 cuốn này bạn đều có thể dễ dàng tìm thấy trên mạng. Theo mình được biết thì chưa có sách tiếng Việt về chủ đề này.
Chúc bạn học tốt.
Với Code trên thì không phải tạo duy nhất một instance.bạn có thể thử đoạn code sau:
Singleton *pInstance;
pInstance = Singleton::Instance();
Singleton instance(*pInstance);