Post date: Jul 4, 2011 5:21:24 PM
Qua những bài vừa qua, ta thấy mô hình singleton được áp dụng khá nhiều, và những đoạn code tương tự nhau được viết lại khá nhiều lần. Trong phần này, ta sẽ thiết kế một lớp tổng quát cho các singleton
CSingleton.h
#ifndef __CSingleton_h__ #define __CSingleton_h__ template <class Singleton> class CSingleton { public: static Singleton* GetInstance() { if (!s_pSingletonInstance) { s_pSingletonInstance = new Singleton(); } return s_pSingletonInstance; } protected: static Singleton* s_pSingletonInstance; }; template Singleton* CSingleton::s_pSingletonInstance = 0; #endif
Các lớp Singleton khác thừa kế từ lớp này, ví dụ:
CStateManagement.h
#ifndef __CSTATEMANAGEMENT_H__ #define __CSTATEMANAGEMENT_H__ #include "CState.h" #include "CSingleton.h" namespace GameTutor { class CStateManagement: public CSingleton<CStateManagement> { friend class CSingleton<CStateManagement>; protected: CStateManagement():m_pCurrentState(0), m_pNextState(0) {} protected: CState* m_pCurrentState; CState* m_pNextState; public: void Update(bool isPause); void SwitchState(CState* nextState); }; } #endif
Lúc này, vai trò của file CStateManagement.cpp kết thúc.
Các lớp thừa kế từ CSingleton có đặc điểm chung:
Một biến thể khác của CSingleton là CAbsSingleton, trong đó, hame GetInstance không đóng vai trò tạo Instance. Instance được thiết lập bởi SetInstance. Thường thay thế cho CSingleton trong trường hợp sử dụng với lớp Abstract (pure virtual class)
CAbsSingleton
template <class AbsSingleton> class CAbsSingleton { public: static AbsSingleton* GetInstance() { return s_pSingletonInstance; } protected: static AbsSingleton* s_pSingletonInstance; void SetInstance(AbsSingleton* val) { if (!s_pSingletonInstance) { s_pSingletonInstance = val; } else { Log("[WARNING] [CAbsSingleton] Singleton instance has been set before."); } } }; template AbsSingleton* CAbsSingleton::s_pSingletonInstance = 0;
Như đã trình bày ở trên, mỗi Singleton sẽ có một thể hiện instance dưới dạng biến con trỏ static. Vùng nhớ được trỏ tới bởi biến con trỏ này sẽ không bao giờ được hủy, dẫn đến rò rĩ bộ nhớ (leak memory). Việc rò rĩ này không ảnh hưởng tới game (instance luôn tồn tại trong suốt quá trình diễn biến của game). Tuy nhiên, nó có thể gây ảnh hưởng không tốt đến nền tảng mà game thực thi (như hệ điều hành). Do đó, cần phải dọn dẹp sạch sẽ vùng nhớ này khi kết thúc game.
Khi này, 2 hàm mới được bổ sung là:
template <class Singleton>
class CSingleton
{
public:
static bool IsAvailable()
{
return s_pSingletonInstance!=0;
}
static void FreeInstance()
{
SAFE_DEL(s_pSingletonInstance);
}
static Singleton* GetInstance()
{
if (!s_pSingletonInstance)
{
s_pSingletonInstance = new Singleton();
}
return s_pSingletonInstance;
}
protected:
static Singleton* s_pSingletonInstance;
};
Để thuận tiện trong việc phát triển source, source được tái cấu trúc như sau:
Cấu trúc thư mục gametutor
Project Demo gồm các files: CExample, main, CStateLogo, CStatePoster
Project gametutor gồm các thư mục:
Cấu trúc solution
(Xem gametutor/project/vs2010/gametutor.sln)
Xem source để có thê chi tiết (Source đã được chỉnh sửa một số chỗ để phù hợp với cấu trúc mới)
Download source code here