我還是在下邊加入關於單件的相關說明先:
//****************************************************************
//3.5 SINGLETON(單件)—對象創建型模式
//1. 意圖
// 保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
//2. 動機
// 對一些類來說,只有一個實例是很重要的。雖然系統中可以有許多打印機,但卻只應該有一個打印假脫機( printer spooler),只應該有
一個文件系統和一個窗口管理器。一個數字濾波器只能有一個A / D轉換器。一個會計系統只能專用於一個公司。
// 我們怎麼樣才能保證一個類只有一個實例並且這個實例易於被訪問呢?
//一個全局變量使得一個對象可以被訪問,但它不能防止你實例化多個對象。 一個更好的辦法是,讓類自身負責保存它的唯一實例。這個類可以保證沒有其他實例可以被創建(通過截取創建新對象的請求),並且它可以提供一個訪問該實例的方法。這就是Singleton模式。
//3. 適用性
// 在下面的情況下可以使用Singleton模式
//. 當類只能有一個實例而且客戶可以從一個衆所周知的訪問點訪問它時。當這個唯一實例應該是通過子類化可擴展的,並且客戶應該無需更改
//代碼就能使用一個擴展的實例時。
//4. 結構
//5. 參與者
//. Singleton
//— 定義一個GetInstance操作,允許客戶訪問它的唯一實例。GetInstance是一個類操作(即Smalltalk中的一個類方法和C++中的一個靜態成員函數)。
//— 可能負責創建它自己的唯一實例。
//6. 協作
//. 客戶只能通過Singleton的GetInstance操作訪問一個Singleton的實例。
//7. 效果
// Singleton模式有許多優點:
//1) 對唯一實例的受控訪問因爲Singleton類封裝它的唯一實例,所以它可以嚴格的控制客戶怎樣以及何時訪問它。
//2) 縮小名空間Singleton模式是對全局變量的一種改進。它避免了那些存儲唯一實例的全局變量污染名空間。
//3) 允許對操作和表示的精化Singleton類可以有子類,而且用這個擴展類的實例來配置一個應用是很容易的。你可以用你所需要的類的實例在運行時刻配置應用。
//4) 允許可變數目的實例這個模式使得你易於改變你的想法,並允許Singleton類的多個實例。此外,你可以用相同的方法來控制應用所使用的
//實例的數目。只有允許訪問Singleton實例的操作需要改變。
//5) 比類操作更靈活另一種封裝單件功能的方式是使用類操作(即C++中的靜態成員函數或者是Smalltalk中的類方法)。但這兩種語言技術都難以改變設計以允許一個類有多個實例。
// 此外,C++中的靜態成員函數不是虛函數,因此子類不能多態的重定義它們。
//8. 實現
class Singleton{
static std::auto_ptr<Singleton> m_pInstance;
protected:
//prevent user making our any instance by manually
Singleton(){}
public:
~Singleton(){}
//Return this singleton class' instance pointer
static Singleton* Instance(){
if(!m_pInstance.get()){
m_pInstance = std::auto_ptr<Singleton>(new Singleton());
}
return m_pInstance.get();
}
};
如上,實現一個單件本身是如此的簡單,甚至無須廢話。
怎樣來使用它呢?
不要試圖從這個類派生你的單件子類,那樣的結果是不妥當的,如果你需要多個單件子類,還是使用下面的宏定義更爲妥當:
#define DEFINE_SINGLETON(cls)/
private:/
static std::auto_ptr<cls> m_pInstance;/
protected:/
cls(){}/
public:/
~cls(){}/
static cls* Instance(){/
if(!m_pInstance.get()){/
m_pInstance = std::auto_ptr<cls>(new cls());/
}/
return m_pInstance.get();/
}
#define IMPLEMENT_SINGLETON(cls) /
std::auto_ptr<cls> cls::m_pInstance(NULL);
假定你需要實現一個單件類YY,這樣書寫:
class YY {
DEFINE_SINGLETON(YY);
public:
//your interfaces here...
};
在cpp文件中,書寫:
IMPLEMENT_SINGLETON(YY);
需要引入這個類的實例的時候,使用這樣的語句:
YY* pYY = YY::Instance();
這,就是全部。
如果需要定義其他的單件類,重複上面的定義,就可以了。
說了這麼多,單件有什麼用途?
請仔細閱讀上面的動機部分。我再附加這些情況:
當想集中管理一個應用程序所需的所有配置時,可以聲明一個CToolsOptions的類,其中包含配置屬性集合。對於這個類的實例,顯然是一個實例就夠了;
當
編寫繪圖程序時,考慮繪製矩形,圓形等分別使用CGraphTool派生的工具類,每個派生類負責處理具體的繪製動作和相關的UI相應邏輯。這些工具類典
型的在被用戶選擇工具欄的圖元按鈕時被選中。依照這種模式,你應該對所有的圖元工具從事註冊工作,使得繪圖程序瞭解運行時刻可以使用那些圖元工具。同樣
的,負責管理註冊信息的這個管理器也只需要一個實例就行了。
留心一下你的周圍,單件實在是典型到不能再典型的例子,以至於隨處可見。
各種設計模式在良好的設計代碼中同樣如此。
想要書寫專家式的優雅代碼,掌握模式是一種必須的手段。