前言:看到我的標題你也許會很奇怪,明明是討論單例模式,為什麼又說不僅僅是單例模式呢?圖樣圖森破!我在這裡想和大家分享的不僅僅是JAVA設計模式中的單例模式(Singleton),還有C++中的單例模式,以及單例模式的原理。總之一句話,不服來辯!
對於很多從事JAVA編程或者C++編程超過1年的工友來說,就單例模式而言可謂是熟悉的不能再熟悉了吧?So easy!簡單的說,就是保持對一個實例的全局范圍內的唯一訪問途徑。上面的話有點繞口,換言之就是無論我們在其他任何類的代碼中想要訪問某個類的實例,都可以通過單例模式或者在全局范圍內唯一的該實例,就像下面的代碼:
[java]
class Singleton{
private static Singleton instance;
private Singleton(){
//todo
}
public static Singleton getInstance(){
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
上面這段是Java的單例模式的簡單實現,有幾點值得我們注意:
(1)類Singleton的構造方法是private的,其成員對象也是private的,這就保證了只能通過單例模式提供的方法來訪問該類的實例。
(2)成員對象instance是static的,這是單例模式的原理和重點。為什麼?容本屌細細道來,在java中,static關鍵字的含義就是不屬於任何類的實例,而是屬於類本身,更重要的是,static修飾的對象和變量會在類第一次被加載時存儲在內存中的靜態儲存區域,只要程序在運行,這塊區域就不會被清除掉,也就是說static修飾的instance會一直保存在靜態儲存區域並且只有一份。所以我們在其他類訪問instance的時候,都是訪問的這塊區域,這就是單例模式的原理所在。
(3)在其他類的代碼中要訪問Singleton實例都可以通過如下的方法:
[java]
Singleton singleton = Singleton.getInstance();
(4)扯點題外話,getInstance方法在多線程的情況下,最好加上同步的關鍵字,以免發生意外情況。
好了,上面我們討論了下java中的單例模式,那麼在C++中的單例模式又是怎麼樣的呢?其實大同小異,只是C++中有了全局變量一說,所以略有不同,我們以Android系統中的ProcessState.cpp為例講解下:
在frameworks/frameworks/base/include/private/binder的Static.h中,聲明了一個全局變量
[cpp]
// For ProcessState.cpp
extern sp<ProcessState> gProcess;
而在frameworks/frameworks/base/libs/binder的ProcessState.cpp中,針對這個全局變量提供了單例模式:
[cpp]
#include <private/binder/Static.h>
...................................
sp<ProcessState> ProcessState::self()
{
if (gProcess != NULL) return gProcess;
AutoMutex _l(gProcessMutex);
if (gProcess == NULL) gProcess = new ProcessState;
return gProcess;
}
ProcessState對於每個進程來說都是獨一無二的,所以Android系統為ProcessState設計了單例模式來訪問它,就像下面這樣的代碼
[cpp]
ProcessState::self()
而ProcessState的構造函數是ProcessState.h中是private的,所以我們無法在其它類中直接調用構造函數來實例化
[cpp]
private:
friend class IPCThreadState;
ProcessState();
~ProcessState();