2012-09-22 133 views
4

我已經看到了這個特定的實施Singleton模式隨處可見:Singleton模式實現

+ (CargoBay *)sharedManager { 
    static CargoBay *_sharedManager = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     _sharedManager = [[CargoBay alloc] init]; 
    }); 
    return _sharedManager; 
} 

,它似乎被接納爲好的做法(這其中尤其是從CargoBay)。

我不明白的唯一部分是第一行static CargoBay *_sharedManager = nil;

爲什麼你將static變量設置爲nil

回答

8

這只是一個可讀性,慣例和實踐的問題。這不是真的需要,因爲:

一。它的價值永遠不會被檢查。在老單的實現有曾經是著名的

+ (id)sharedInstance 
{ 
    static SomeClass *shared = nil; 
    if (shared == nil) 
     shared = [[SomeClass alloc] init]; 

    return shared; 
} 

碼 - 此方法的工作,支持變量被初始化到零,因爲如果不是零的第一次,它會錯誤地省略if部分中的alloc-init並返回一個垃圾指針。但是,使用GCD解決方案時,不再需要無檢查 - GCD處理'只執行一次'編譯指示。

二。但是:靜態變量隱含地初始化爲零。所以即使你只寫static id shared;它最初也會是nil

三。爲什麼這可能是好的做法?因爲,儘管我提到了前兩個原因,但讓源代碼的讀者知道某些內容已明確初始化爲零仍然更具可讀性。或者甚至可能存在一些不合格的實現,其中靜態變量未正確自動初始化,然後應採取此操作。

+0

很好,謝謝你的回答。但是,爲什麼靜態? – Francesco

+0

@Francesco你是什麼意思? – 2012-09-22 15:43:46

+0

通過聲明共享實例'static',我們將其生命週期延長到整個應用程序的生命週期,對吧? Singleton模式的要點是有一個共享實例,可以在我們的應用程序的任何地方使用,但是爲什麼我們每次調用該方法時都會創建一個新實例? – Francesco

1

您將它設置爲零以確保您獲得乾淨的實例。

這是你想要做什麼更可讀的版本:

+ (GlobalVariables *)sharedInstance { 
    // the instance of this class is stored here 
    static GlobalVariables *myInstance = nil; 

    // check to see if an instance already exists 
    if (nil == myInstance) { 
     myInstance = [[[self class] alloc] init]; 
    } 
    // return the instance of this class 
    return myInstance; 
} 

但也有職位的負載各地展示這可怎麼可能不是線程安全的,所以移動到你的方法的混合體上面和我發佈的東西,你得到這個:

// Declared outside Singleton Manager  
static SingletonClass *myInstance = nil; 
+ (GlobalVariables *)sharedInstance { 
    if (nil != myInstance) { 
     return myInstance; 
    } 

    static dispatch_once_t pred;  // Lock 
    dispatch_once(&pred, ^{    // This code is called at most once per app 
     myInstance = [[GlobalVariables alloc] init]; 
    }); 

    return myInstance; 
} 
+0

「你引用的代碼塊不會總是重複使用同一個實例」 - 這只是*不正確。* – 2012-09-22 15:10:24

+0

由GCD覆蓋執行一次的代碼是dispatch_once塊內的代碼,而不是其外部的代碼。我寫的內容主要是試圖通過簡單地添加對共享實例的檢查來提高可讀性。在Singleton訪問器之外移動共享實例的分配使得整個過程變得清晰。 – MystikSpiral

+0

'賦值'不是一個真正的'賦值',而是一個初始化。因爲被初始化的變量是'static',所以它將被執行(初始化)一次,不管它的範圍,它被聲明/初始化的地方等***維基百科的[第一個例子](http: //en.wikipedia.org/wiki/Static_variable)明確指出*「x僅在func()的三次調用中初始化一次...」...... * – 2012-09-22 15:23:22