單例(單態)模式
單例設計模式確保對於一個給定的類只有一個實例存在,這個實例有一個全局唯一的訪問點。它通常采用懶加載的方式在第一次用到實例的時候再去創建它。
注意:蘋果大量使用了此模式。例如:[NSUserDefaults standardUserDefaults], [UIApplication sharedApplication], [UIScreen mainScreen], [NSFileManager defaultManager],所有的這些方法都返回一個單例對象。
你很可能會想為什么這么關心是否一個類有多個實例?畢竟代碼和內存都是廉價的,對嗎?
有一些情況下,只有一個實例顯得非常合理。舉例來說,你不需要有多個Logger的實例,除非你想去寫多個日志文件。或者一個全局的配置處理類:實現線程安全的方式訪問共享實例是容易的,比如一個配置文件,有好多個類同時修改這個文件。
如何使用單例模式
首先來看看下面的圖:

上面的圖描述了一個有單一屬性(它就是單一實例)和sharedInstance,init兩個方法的類。
客戶端第一次發送sharedInstance消息的時候,instance屬性尚未被初始化,所以此時你需要創建一個新的實例,然后返回它的引用。
當你下一次調用sharedInstance的時候,instance不需要任何初始化可以立即返回。這個邏輯保證總是只有一個實例。
你接下來將用這個模式來創建一個管理所有專輯數據的類。
你將注意到工程中有一個API的組,在這個組里你可以放入給你應用提供服務的所有類。在此組中,用IOS\Cocoa Touch\Objective-C class 模板創建一個新類,命名它為LibraryAPI,設置父類為NSObject.
打開LibraryAPI.h,用如下代碼替換它的內容
- @interfaceLibraryAPI : NSObject
- + (LibraryAPI*)sharedInstance;
- @end
現在打開LibraryAPI.m,在@implementation 那一行后面插入下面的方法:
- + (LibraryAPI*)sharedInstance
- {
- // 1
- static LibraryAPI *_sharedInstance = nil;
- // 2
- static dispatch_once_t oncePredicate;
- // 3
- dispatch_once(&oncePredicate, ^{
- _sharedInstance = [[LibraryAPI alloc] init];
- });
- return _sharedInstance;
- }
在這個簡短的方法中,有一些需要需要注意的點:
1.聲明一個靜態變量去保存類的實例,確保它在類中的全局可用性。
2.聲明一個靜態變量dispatch_once_t ,它確保初始化器代碼只執行一次
3.使用Grand Central Dispatch(GCD)執行初始化LibraryAPI變量的block.這 正是單例模式的關鍵:一旦類已經被初始化,初始化器永遠不會再被調用。
下一次你調用sharedInstance的時候,dispatch_once塊中的代碼將不會執行(因為它已經被執行了一次),你將得到原先已經初始化好的實例。
注意: 為了學習更多關於GCD方面的信息以及如何使用,請查看本站指南
Multithreading and Grand Central Dispatch 和
How to Use Blocks。