靜態變量和單例模式


靜態變量和單例模式

 

1.靜態變量

靜態變量Static Variable)在計算機編程領域指在程序執行前系統就為之靜態分配(也即在運行時不再改變分配情況)存儲空間的一類變量。與之相對應的是在運行時只暫時存在的自動變量(即局部變量)與以動態分配方式獲取存儲空間的一些對象,其中自動變量的存儲空間在調用棧上分配與釋放。

不同情況下的作用

除明確標識出變量的生命周期外,將變量聲明為static存儲類還會根據變量屬性不同而有一些特殊的作用:

  • 對於靜態全局變量來說,針對某一源文件的以static聲明的文件級變量與函數的作用域只限於文件內(只在文件內可見),也即“內部連接”,因而可以用來限定變量的作用域;
  • 對於靜態局部變量來說,在函數內以static聲明的變量雖然與自動局部變量的作用域相同(即作用域都只限於函數內),但存儲空間是以靜態分配而非默認的自動分配方式獲取的,因而存儲空間所在區域不同(一般來說,靜態分配時存儲空間於編譯時在程序數據段分配,一次分配全程有效;而自動分配時存儲空間則是於調用棧上分配,只在調用時分配與釋放),且兩次調用間變量值始終保持一致;
  • 對於靜態成員變量來說,在C++中,在類的定義中以static聲明的成員變量屬於類變量,也即在所有類實例中共享,與之相對的就是過程變量。

C示例

在C語言中,帶有靜態變量的程序如下所示:

#include <stdio.h>
 
void func() {
    static int x = 0; // 在對func的三次調用中,x只進行一次初始化
    printf("%d\n", x); // 輸出x的值
    x = x + 1;
}
 
int main(int argc, char * const argv[]) {
    func(); // 輸出0
    func(); // 輸出1
    func(); // 輸出2
    return 0;
}

 

2.單例模式

  一個單例的類,無論一個應用請求它多少次,都將返回一個相同的實例。一個典型的類允許調用者創建很多實例,而對於單例類來說,一個進程中只能有一個類的實例。一個單例對象提供了全局訪問其類的資源的點。單例常被用在這種單點控制被滿足的情況下,例如一些類需要提供公用的服務或者資源。

 

你應該從一個單例類的工廠方法中獲得一個全局實例。當第一次被請求的時候這個類應該懶加載一個唯一的實例,並且保證之后沒有其他實例被創建。。一個單例類同時也組織調用者對它實例進行copying,retaining,或者releasing。

在一些Cocoa的框架中用到單例。其中有,NSFileManager,NSWorkspace。在UIKit,UIApplication 和 UIAccelerometer也用到單例。工廠方法以sharedClassType這種名字,方便的返回一個單例對象。例如,在Cocoa框架中,sharedFileManager,sharedColorPanel,sharedWorkspace。

 

 3. IOS中單例的創建

  有了上面的知識,我們就比較容易理解單例的創建方式了。首先介紹兩種單例的創建方式。

static AccountManager *DefaultManager = nil;
 
+ (AccountManager *)defaultManager {
    if (!DefaultManager) DefaultManager = [[self allocWithZone:NULL] init];
    return DefaultManager;
}

在iOS4之后有了另外一種寫法:

+ (AccountManager *)sharedManager
{
        static AccountManager *sharedAccountManagerInstance = nil;
        static dispatch_once_t predicate;
        dispatch_once(&predicate, ^{
                sharedAccountManagerInstance = [[self alloc] init]; 
        });
    return sharedAccountManagerInstance;
}

 

  無論上面的方法被調用幾次,靜態變量總初始化一次。關於dispatch_once這個方法,官方是這樣說的:在一個應用的生命周期中執行一個block對象一次且僅一次。predicate參數是一個指向dispatch_once_t結構的指針,用來判斷block有沒有被完成執行。block參數是那個被執行一次的塊。dispatch_once這個函數對於初始化一個應用中的全局數據如單例是很有用的。在使用block塊中初始化的變量的時候,需要首先調用這個函數。如果在多線程情況下同時調用,這個函數同步等待block塊中的內容執行完畢。predicate必須指向一個全局或靜態變量。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM