iOS單例模式(全文無恥COPY)后補(bǔ)個人錯誤點評

iOS設(shè)計模式——單例模式
http://blog.csdn.net/lovefqing/article/details/8516536

單例模式用于當(dāng)一個類只能有一個實例的時候, 通常情況下這個“單例”代表的是某一個物理設(shè)備比如打印機(jī),或是某種不可以有多個實例同時存在的虛擬資源或是系統(tǒng)屬性比如一個程序的某個引擎或是數(shù)據(jù)。用單例模式加以控制是非常有必要的。

單例模式需要達(dá)到的目的

  1. 封裝一個共享的資源

  2. 提供一個固定的實例創(chuàng)建方法

  3. 提供一個標(biāo)準(zhǔn)的實例訪問接口

單例模式的創(chuàng)建
本文以創(chuàng)建一個MySingletonClass的單例模式為例。首先,我們需要定義一個類MySingletonClass.

[cpp] view plain copy
@interface MySingletonClass:NSObject {

}

并且為其添加一個類方法(注意,這里不是實例方法)+(id)sharedInstance;一個基本的實現(xiàn)寫法如下:

[cpp] view plain copy
static MySingletonClass *sharedCLDelegate = nil;
+(MySingletonClass *)sharedInstance{
@synchronized(self) {
if(sharedCLDelegate == nil) {
[[[self class] alloc] init]; // assignment not done here
}
}
return sharedCLDelegate;
}
在上面的代碼中(用到了關(guān)鍵字@synchronized是為了保證我們的單例的線程級別的安全,可以適用于多線程模式下。)static變量sharedCLDelegate用于存儲一個單例的指針,并且強(qiáng)制所有對該變量的訪問都必須通過類方法 +(id)sharedInstance,在對 +(id)sharedInstance第一次調(diào)用時候完成實例的創(chuàng)建。這里值得留意一下的是,上面代碼中用的是[[selfclass] alloc],而不是 [MySingletonClass alloc],一般情況下這兩種寫法產(chǎn)生同樣的效果,但是這里這樣做是為了更好的利用OOP的性質(zhì),[selfclass]可以動態(tài)查找并確定類的類型從而便于實現(xiàn)對該類的子類化。

對實例化的控制
為了完全的實現(xiàn)實例的單態(tài)性,必須通過一定手段來避免實例多次被創(chuàng)建。+(id)sharedInstance控制了單例的創(chuàng)建和訪問,但是并不能控制其它地方的代碼通過alloc方法來創(chuàng)建更多的實例,因此我們還要重載任何一個涉及到allocation的方法,這些方法包括 +new, +alloc,+allocWithZone:, -copyWithZone:, 以及 -mutableCopyWithZone: 另外,+(id)sharedInstance也需要稍作修改。

[cpp] view plain copy

  • (id)hiddenAlloc
    {
    return [super alloc];
    }
  • (id)alloc
    {
    NSLog(@"%@: use +sharedInstance instead of +alloc", [[self class] name]);
    return nil;
    }
  • (id)new
    {
    return [self alloc];
    }

+(id)allocWithZone:(NSZone*)zone
{
return [self alloc];
}

  • (id)copyWithZone:(NSZone *)zone
    { // -copy inherited from NSObject calls -copyWithZone:
    NSLog(@"MySingletonClass: attempt to -copy may be a bug.");
    [self retain];
    return self;
    }

  • (id)mutableCopyWithZone:(NSZone *)zone
    {
    // -mutableCopy inherited from NSObject calls -mutableCopyWithZone:
    return [self copyWithZone:zone];
    }

+(id)sharedInstance修改如下:

  • (MySingletonClass *)sharedInstance {
    @synchronized(self) {
    if (sharedCLDelegate == nil) {
    [[[self class] hiddenAlloc] init]; // assignment not done here
    }
    }
    return sharedCLDelegate;
    }
    如果不考慮類的子類化,+hiddenAlloc這個方法可以省略。由于我們是用[selfclass]來實現(xiàn)類型的動態(tài)識別,用[[selfclass] hiddenAlloc]可以避免調(diào)用到被重載過的alloc方法。此外,hiddenAlloc也為可能的子類化提供了一個調(diào)用原始alloc方法的機(jī)會。上面重載過的alloc方法只是給出一個log信息并且返回nil。Copying方法里只是簡單的增加了retain的計數(shù)并沒有返回一個新的實例。這也正體現(xiàn)了單例模式的性質(zhì),因為技術(shù)上來講,拷貝一個單例是錯誤的(因為是“單例”)所以在copyWithZone方法中我們給出了一個錯誤信息,當(dāng)然也可以扔出一個exception。

單例的銷毀
通常我們在 -(void)applicationWillTerminate:(UIApplication *)application方法中調(diào)用如下方法:

[cpp] view plain copy

  • (void)attemptDealloc
    {
    if ([sharedCLDelegate retainCount] != 1)
    return;

    [sharedCLDelegate release];
    myInstance = nil;
    }

值得注意的是,上面這個attemptDealloc方法顧名思義,只是試圖釋放掉這個單例。如果retain的計數(shù)不為1,說明還有其他地方對該單例發(fā)送過retain消息??紤]到一個單例模式的生存周期是整個程序結(jié)束為止。所以,在程序的任何一個地方都沒有必要向這個單例發(fā)送retain消息,即便是對這個單例有引用。而是調(diào)用sharedInstance方法來引用這個單例,這樣做是安全的,也是合乎單例模式的技術(shù)含義的。

iOS中的單例模式應(yīng)用
iOS中好幾個類都是采用了單例模式,比如NSApplication, NSFontManager, NSDocumentController,NSHelpManager, NSNull,NSProcessInfo, NSScriptExecutionContext, NSUserDefaults.

如果本文有任何錯誤之處,歡迎拍磚指正,共同進(jìn)步, 謝謝!

個人錯解:
需要寫了+shareinstance;但忽略了,alloc.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 單例模式 什么是單例模式? 單例模式想一個大獨裁者,他規(guī)定在他的國度里面,所有數(shù)據(jù)的訪問和請求都得經(jīng)過他,甚至你要...
    GitHubPorter閱讀 1,253評論 0 4
  • 單例:意思就是只有一個實例。單例模式確保某一個類只有一個實例,而且自行實例化并向整個系統(tǒng)提供這個實例。這個類稱為單...
    CoderZS閱讀 639評論 1 13
  • 設(shè)計模式 從設(shè)計模式的角度分析Delegate、Notification、KVO的區(qū)別 三者優(yōu)缺點: delega...
    b485c88ab697閱讀 4,690評論 0 23
  • 在開發(fā)中經(jīng)常會用到單例設(shè)計模式,目的就是為了在程序的整個生命周期內(nèi),只會創(chuàng)建一個類的實例對象,而且只要程序不被殺死...
    不要重名就好閱讀 596評論 0 0
  • autohotkey的循環(huán)是用loop關(guān)鍵字,比較簡單。如果要10次循環(huán),那么可以用loop, 10 {循環(huán)} 在...
    科幻經(jīng)典閱讀 2,858評論 0 0

友情鏈接更多精彩內(nèi)容