最簡單的設(shè)計模式學(xué)習(xí):Singleton模式
學(xué)習(xí)設(shè)計模式,自然從最簡單的模式入手,而最簡單的模式便是Singleton。所以***篇就來所以說Singleton模式??赐闓OF和Design patterns in Java的書,感覺Singleton雖然簡單,但是想寫出一個好的Singleton也不是一上來就能寫出來的。
Singleton模式的用處自然是保證一個類只有一個***的實例。在建模中涉及到的只能有一個對象,例如Struts中的Action類就是一例。除此之外,Singleton還使得該對象只有一個全局訪問點(diǎn)。這就是SIngleton的作用。
說得比較抽象,我們來看一個簡單Singleton的C++和Java的代碼:
C++ Singleton模式:
類定義:
- class Singleton
- {
- public:
- static Singleton * Instance();
- ~Singleton();
- private:
- Singleton();
- static Singleton * instance;
- };
方法實現(xiàn):
- 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的實現(xiàn)并不難,只要將構(gòu)造函數(shù)訪問域設(shè)為私有,然后添加一個靜態(tài)引用和一個獲得該應(yīng)用的靜態(tài)方法即可。其實在C++中定義一個全局靜態(tài)變量也可以達(dá)到這個效果,但是像Java這樣的語言就是能使用Singleton了。
上面的程序有一個問題,就是只能運(yùn)行在單線程的環(huán)境下。為此我在C++上作了個實驗。首先#include
- Singleton * Singleton::Instance()
- {
- if (instance == 0) {
- Sleep(1000);
- instance = new Singleton();
- }
- return instance;
- }
然后在主函數(shù)中創(chuàng)建兩個線程,程序如下:
- 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;
- }
這樣修改后在運(yùn)行程序,打印出來的s1和s2地址就不是同一個地址了。結(jié)果如下:
0372D68 00372E68Press any key to continue
可見當(dāng)在多線程環(huán)境下使用這個Singleton就會出現(xiàn)創(chuàng)建不止一個實力的情況,所以我們需要給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() {
- }
- }
運(yùn)用加鎖就可以解決在多線程環(huán)境下使用Singleton模式所帶來的問題了。
【編輯推薦】