基於android2.3.5系統:Android中native層C++單例模式

***************************************************************************************************************************
作者:EasyWave                                                                                 時間:2013.02.16

類別:Android系統源碼分析                                                              聲明:轉載,請保留鏈接

注意:如有錯誤,歡迎指正。這些是我學習的日誌文章......

***************************************************************************************************************************

一:什麼是單例模式

       單例模式也稱爲單件模式、單子模式,可能是使用最廣泛的設計模式。其意圖是保證一個類僅有一個實例,並提供一個訪問它的全局訪問點,該實例被所有程序模塊共享。單例模式有許多種實現方法,在C++中,甚至可以直接用一個全局變量做到這一點。使用全局對象能夠保證方便地訪問實例,但是不能保證只聲明一個對象——也就是說除了一個全局實例外,仍然能創建相同類的本地實例。《設計模式》中文版一書中給出了一種很不錯的實現,在84頁開始講這個單例模式。具體的可以參考書中所說。

二:單例模式的優點

1) 對唯一實例的受控訪問

       因爲Singleton類封裝它的唯一實例,所以它可以嚴格的控制客戶怎樣以及何時訪問它。
2) 縮小名空間

      Singleton模式是對全局變量的一種改進。它避免了那些存儲唯一實例的全局變量污染名空間。
3) 允許對操作和表示的精化

        Singleton類可以有子類,而且用這個擴展類的實例來配置一個應用是很容易的。你可以用你所需要的類的實例在運行時刻配置應用。
4) 允許可變數目的實例

       這個模式使得你易於改變你的想法,並允許Singleton類的多個實例。此外,你可以用相同的方法來控制應用所使用的實例的數目。只有允許訪問Singleton實例的操作需要改變。
5) 比類操作更靈活

        另一種封裝單件功能的方式是使用類操作(即C + +中的靜態成員函數或者是Smalltalk中的類方法)。但這兩種語言技術都難以改變設計以允許一個類有多個實例。此外,C++中的靜態成員函數不是虛函數,因此子類不能多態的重定義它們。

三:Android系統中實現的單例模式

      在Android系統中,我們可以在很多地方看到這種設計模式,比如ProcessState類、IPCThreadState類等。我們還是來看看他們的實現代碼吧。在frameworks\base\libs\binder\ProcessState.cpp文件中我們可以看到如下的定義:

而sp<ProcessState> self()定義是在frameworks\base\include\binde\ProcessState.h文件中,如下:

       仔細看紅色圈中的部分,從上面的代碼中,我們看出這是一個典型的C++的單例模式,gProcess是在Static.cpp中定義的,用戶訪問唯一實例的方法只有self()成員函數。如果不通過這個函數,任何創建實例的嘗試都將失敗,因爲類的構造函數是私有的。self()使用懶惰初始化,也就是說它的返回值是當這個函數首次被訪問時被創建的。這是一種防彈設計——所有self()之後的調用都返回相同實例的指針,那麼它是如何調用的呢?如下:[在frameworks\base\cmds\app_process\App_main.cpp]

在Andriod中,還有一個地方,這裏需要特別的說說,就是在frameworks\base\libs\binder\IPCThreadState.cpp文件中,這個關於binder的進程間通信的類函數集合。它的調用方式採用了TLS,也就是線程局部存儲(Thread Local Storage,TLS)。Andriod是一個多線程的系統,每個線程除了共享進程的資源外還擁有各自的私有資源:
一個寄存器組(或者說是線程上下文);
一個專屬的堆棧;
一個專屬的消息隊列;
一個專屬的Thread Local Storage(TLS);
一個專屬的結構化異常處理串鏈。

這裏重點關注Thread Local Storage,我們還是來看看具體的代碼實現吧,如下:

       不錯,pthread_getspecific()和pthread_key_create()函數就是一個關於TLS相關的函數。詳細的關於線程的概念,請參考:《POSIX多線程程序設計》這本書。這本書詳細的解釋了Linux下的線程的概念。這裏採用了TLS來作爲用戶訪問唯一實例。這個地方用的非常巧妙...... 深入的知識點就不說了......

如何調用呢?請看frameworks\base\core\jni\android_util_Binder.cpp中的static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name)函數,如下:

      在Andriod的源碼中,很多地方採用可複用面向對象軟件的設計模式,所以,建議還是先看看《設計模式精解-GoF 23 種設計模式解析附 C++實現源碼》,可以在下面的地址下載,分C++版和Java版:

C++版:http://wenku.baidu.com/view/69b6c04b2b160b4e767fcff5.html

Java版:http://wenku.baidu.com/view/bbf5e9d633d4b14e85246884.html 

發佈了111 篇原創文章 · 獲贊 20 · 訪問量 68萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章