iOS設(shè)計模式——單例模式
http://blog.csdn.net/lovefqing/article/details/8516536
單例模式用于當(dāng)一個類只能有一個實(shí)例的時候遂鹊, 通常情況下這個“單例”代表的是某一個物理設(shè)備比如打印機(jī)灾梦,或是某種不可以有多個實(shí)例同時存在的虛擬資源或是系統(tǒng)屬性比如一個程序的某個引擎或是數(shù)據(jù)。用單例模式加以控制是非常有必要的砌们。
單例模式需要達(dá)到的目的
封裝一個共享的資源
提供一個固定的實(shí)例創(chuàng)建方法
提供一個標(biāo)準(zhǔn)的實(shí)例訪問接口
單例模式的創(chuàng)建
本文以創(chuàng)建一個MySingletonClass的單例模式為例贩虾。首先催烘,我們需要定義一個類MySingletonClass.
[cpp] view plain copy
@interface MySingletonClass:NSObject {
}
并且為其添加一個類方法(注意,這里不是實(shí)例方法)+(id)sharedInstance;一個基本的實(shí)現(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)用時候完成實(shí)例的創(chuàng)建舰始。這里值得留意一下的是,上面代碼中用的是[[selfclass] alloc]咽袜,而不是 [MySingletonClass alloc],一般情況下這兩種寫法產(chǎn)生同樣的效果丸卷,但是這里這樣做是為了更好的利用OOP的性質(zhì),[selfclass]可以動態(tài)查找并確定類的類型從而便于實(shí)現(xiàn)對該類的子類化询刹。
對實(shí)例化的控制
為了完全的實(shí)現(xiàn)實(shí)例的單態(tài)性谜嫉,必須通過一定手段來避免實(shí)例多次被創(chuàng)建萎坷。+(id)sharedInstance控制了單例的創(chuàng)建和訪問,但是并不能控制其它地方的代碼通過alloc方法來創(chuàng)建更多的實(shí)例沐兰,因此我們還要重載任何一個涉及到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]來實(shí)現(xiàn)類型的動態(tài)識別寞秃,用[[selfclass] hiddenAlloc]可以避免調(diào)用到被重載過的alloc方法斟叼。此外,hiddenAlloc也為可能的子類化提供了一個調(diào)用原始alloc方法的機(jī)會春寿。上面重載過的alloc方法只是給出一個log信息并且返回nil朗涩。Copying方法里只是簡單的增加了retain的計數(shù)并沒有返回一個新的實(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.