最簡單的設計模式學習:Singleton模式
學習設計模式,自然從最簡單的模式入手,而最簡單的模式便是Singleton。所以***篇就來所以說Singleton模式。看完GOF和Design patterns in Java的書,感覺Singleton雖然簡單,但是想寫出一個好的Singleton也不是一上來就能寫出來的。
Singleton模式的用處自然是保證一個類只有一個***的實例。在建模中涉及到的只能有一個對象,例如Struts中的Action類就是一例。除此之外,Singleton還使得該對象只有一個全局訪問點。這就是SIngleton的作用。
說得比較抽象,我們來看一個簡單Singleton的C++和Java的代碼:
C++ Singleton模式:
類定義:
- class Singleton
- {
- public:
- static Singleton * Instance();
- ~Singleton();
- private:
- Singleton();
- static Singleton * instance;
- };
方法實現:
- Singleton * Singleton::instance = 0;
- Singleton::Singleton()
- {
- }
- Singleton::~Singleton()
- {
- }
- Singleton * Singleton::Instance()
- {
- if (instance == 0) {
- instance = new Singleton();
- }
- return instance;
- }
Java Singleton模式:
- public class Singleton {
- private static Singleton instance;
- public static Singleton getInstance() {
- if (instance == null)
- instance = new Singleton();
- return instance;
- }
- /** *//** Creates a new instance of Singleton */
- private Singleton() {
- }
- }
通過上面的例子可以看出,Singleton的實現并不難,只要將構造函數訪問域設為私有,然后添加一個靜態引用和一個獲得該應用的靜態方法即可。其實在C++中定義一個全局靜態變量也可以達到這個效果,但是像Java這樣的語言就是能使用Singleton了。
上面的程序有一個問題,就是只能運行在單線程的環境下。為此我在C++上作了個實驗。首先#include
- Singleton * Singleton::Instance()
- {
- if (instance == 0) {
- Sleep(1000);
- instance = new Singleton();
- }
- return instance;
- }
然后在主函數中創建兩個線程,程序如下:
- static Singleton * s1 = 0, * s2 = 0;
- DWORD WINAPI ThreadProc1(PVOID)
- {
- s1 = Singleton::Instance();
- return 0;
- }
- DWORD WINAPI ThreadProc2(PVOID)
- {
- s2 = Singleton::Instance();
- return 0;
- }
- int main(int argc, char* argv[])
- {
- DWORD threadID1;
- DWORD threadID2;
- CreateThread(NULL, 0, ThreadProc1, NULL, 0, &threadID1);
- CreateThread(NULL, 0, ThreadProc2, NULL, 0, &threadID2);
- Sleep(10000);
- std::cout << s1 << " " << s2;
- return 0;
- }
這樣修改后在運行程序,打印出來的s1和s2地址就不是同一個地址了。結果如下:
0372D68 00372E68Press any key to continue
可見當在多線程環境下使用這個Singleton就會出現創建不止一個實力的情況,所以我們需要給Singleton加鎖。請看下面的代碼。
C++ Singleton模式:
- class Singleton
- {
- public:
- static Singleton * Instance();
- virtual ~Singleton();
- private:
- Singleton();
- static CMutex mutex;
- static Singleton * instance;
- };
- Singleton * Singleton::instance = 0;
- CMutex Singleton::mutex;
- Singleton::Singleton()
- {
- }
- Singleton::~Singleton()
- {
- }
- Singleton * Singleton::Instance()
- {
- mutex.Lock();
- if (instance == 0) {
- Sleep(1000);
- instance = new Singleton();
- }
- mutex.Unlock();
- return instance;
- }
此外需要#include < afxmt.h>,
Java Singleton模式:
- public class Singleton {
- private static Singleton instance;
- private static Object lock = Singleton.class;
- public static Singleton getInstance() {
- synchronized (lock) {
- if (instance == null)
- instance = new Singleton();
- return instance;
- }
- }
- /** *//** Creates a new instance of Singleton */
- private Singleton() {
- }
- }
運用加鎖就可以解決在多線程環境下使用Singleton模式所帶來的問題了。
【編輯推薦】