說在前面
進入正式的設計模式交流之前,扯點閑話。我們在項目開發的過程中,經常會不經意的使用一些常見的設計模式,如單例模式、工廠方法模式、觀察者模式等,以前做.NET開發的時候,認真拜讀了一下程傑老師的《大話設計模式》,程老師用诙諧的語言,貼近生活的示例,讓我對設計模式有了一個大緻的了解。轉型做IOS開發後,一直想閱讀一下針對IOS設計模式方面的書籍,也買了一本《Objective-C程式設計之道:iOS設計設計模式解析》進行學習,本系列設計模式的文章,有些内容來自這兩本書籍,也有些内容來自于網絡和個人學習過程的整理,算是本人對設計模式學習的筆記,大家對文章中不足的地方,歡迎提出改進的建議。
定義
保證一個類僅有一個執行個體,并提供一個該執行個體的全局通路點。
定義包含三層含義:一是某個類隻能有一個執行個體;二是它必須自行建立這個執行個體;三是它必須向整個系統提供這個執行個體。
結構圖

從結構圖可以看到,單例模式(Singleton)是比較獨立的一個設計模式,它的主要特點是控制某個類的執行個體唯一性,通過上圖我們知道它包含的類隻有一個,就是Singleton。該模式中包含一個靜态私有成員變量mySingleton與類方法sharedInstance()。sharedInstance ()方法負責執行個體化自己,然後存儲在靜态成員mySingleton變量中,以確定隻有一個執行個體被建立。
單例模式的實作
在Objective-C中實作單例模式,需要完成如下四個步驟:
- 第一步:定義一個靜态執行個體變量mySingleton(名字可以自己取),初始化為nil,代碼如下所示:
1 static MySingleton *mySingleton = nil;
- 第二步:實作一個類方法檢查上面聲明的靜态執行個體是否為nil,如果是則建立并傳回一個本類的執行個體,代碼如下所示:
1 + (id)sharedInstance
2 {
3 static dispatch_once_t onceToken;
4 dispatch_once(&onceToken, ^{
5 if(mySingleton == nil)
6 {
7 mySingleton = [[self alloc] init];
8 }
9 });
10 return mySingleton;
11 }
【說明】:dispatch_once函數是GCD中的API,它保證應用程式即使在多線程環境下,也隻執行一次。當然,也可以使用@synchronize來達到線程安全的目的,代碼如下所示:
1 + (id)sharedInstance
2 {
3 @synchronized (self)
4 {
5 if (mySingleton == nil)
6 {
7 mySingleton = [[self alloc] init];
8 }
9 }
10 return mySingleton;
11 }
- 第三步:重寫allocWithZone方法,用來保證使用alloc和init試圖獲得一個新執行個體的時候不産生新執行個體,代碼如下所示:
1 + (id)allocWithZone:(NSZone *)zone
2 {
3 static dispatch_once_t onceToken;
4 dispatch_once(&onceToken, ^{
5 if (mySingleton == nil)
6 {
7 mySingleton = [super allocWithZone:zone];
8 NSLog(@"allocWithZone");
9 }
10 });
11 return mySingleton;
12 }
- 第四步:适當實作copyWithZone,release和autorelease等方法。代碼如下所示:
1 // 如果有其他初始化操作,可在這裡進行初始化
2 - (id)init
3 {
4 self = [super init];
5 if (self != nil)
6 {
7 // 其他初始化操作
8 }
9 return self;
10 }
11
12 // 防止外界拷貝造成多個執行個體,保證執行個體的唯一性。
13 - (id)copyWithZone:(NSZone *)zone
14 {
15 return self;
16 }
17
18 // 因為隻有一個執行個體對象,是以retain不能增加引用計數。
19 - (id)retain
20 {
21 return self;
22 }
23
24 // 因為隻有一個執行個體對象,設定預設引用計數。這裡是取的NSUinteger的最大值,當然也可以設定成1或其他值。
25 - (NSUInteger)retainCount
26 {
27 return UINT_MAX; // denotes an object that cannot be released
28 }
29
30 // oneway是用于多線程程式設計中,表示單向執行,不能“復原”,即原子操作。該方法是空的,不讓使用者release掉這個對象。
31 - (oneway void)release
32 {
33 //do nothing
34 }
35
36 //除了傳回單例外,什麼也不做。
37 - (id)autorelease
38 {
39 return self;
40 }
41
42 // 該方法永遠不會被調用,因為在程式的生命周期内容,該單例一直都存在。(是以該方法可以不實作)
43 - (void)dealloc
44 {
45 [super dealloc];
46 }
【說明】:對于步驟二和步驟三,也可以按如下方式實作:
1 + (id)sharedInstance
2 {
3 @synchronized(self)
4 {
5 if(mySingleton == nil)
6 {
7 mySingleton = [[super allocWithZone:NULL] init];
8 NSLog(@"allocWithZone");
9 }
10 }
11 return mySingleton;
12 }
13
14 // 通過傳回目前的sharedInstance執行個體,就能防止執行個體化一個新的對象。
15 + (id)allocWithZone:(NSZone *)zone
16 {
17 return [[self sharedInstance] retain];
18 }
單例模式在IOS中的應用
單例模式在IOS中的應用非常廣泛,如[NSNotificationCenter defaultCenter]、[UIApplication sharedApplication]、[NSFileManager defaultManager]等。
源碼下載下傳 傳回目錄
循自然之道,撫浮躁之心