定義:
單例模式使用場景,必須一個類只有一個實例,并且提供一個訪問它的全局訪問點。
單例模式的要點有三個;一是某個類只能有一個實例;二是它必須自行創(chuàng)建這個實例;三是它必須自行向整個系統(tǒng)提供這個實例。
從具體實現(xiàn)角度來說,就是以下三點:一是單例模式的類只提供私有的構造函數,二是類定義中含有一個該類的靜態(tài)私有對象,三是該類提供了一個靜態(tài)的公有的函數用于創(chuàng)建或獲取它本身的靜態(tài)私有對象
在 Cocoa Touch中 比較代表的就是 UIApplication ---[UIApplication sharedApplication]。
下面我們來思考幾個問題
1、我們?yōu)槭裁匆脤嵗龑ο蠖皇穷悓ο螅?br> OC的類對象可以接受消息,也可以在其他對象中調用,而且runtime確保類在application生命周期內只初始化一次。
答案是:因為增加維護成本。(已經存在一個類,你想寫個子類去實現(xiàn)同樣的事情。首先使用的是類方法調用,那么你得替換所有的方法調用類名稱)。
注意我們應該盡量避免硬編碼類名,這樣增加了將來維護的難度
解決方法:使用一個全局變量 存儲使用的指針。
2、 那么直接使用全局變量的指針 是不是就完美了呢?
答案是:否。靜態(tài)的全局變量,和對象的實例變量 比起來維護性太差。不具有面向對象的可以繼承的能力。方法和變量也不具有多態(tài)的好處。
嚴謹的單例的創(chuàng)建:
static Singleton *_sharedSingleton = nil;
@implementation Singleton
- (instancetype)init {
[NSException raise:@"SingletonPattern"
format:@"Cannot instantiate singleton using init method, sharedInstance must be used."];
return nil;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
if (self != [Singleton class]) {
[NSException raise:@"SingletonPattern"
format:@"Cannot use sharedInstance method from subclass."];
}
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedSingleton = [[Singleton alloc] initInstance];
});
return _sharedSingleton;
}
+ (instancetype)new {
return [self alloc];
}
- (instancetype)copyWithZone:(NSZone *)zone {
return _sharedSingleton;
}
- (instancetype)mutableCopyWithZone:(NSZone *)zone {
return [self copyWithZone:zone];
}
+ (Singleton *)sharedInstance {
if (self != [Singleton class]) {
[NSException raise:@"SingletonPattern"
format:@"Cannot use sharedInstance method from subclass."];
}
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedSingleton = [[Singleton alloc] initInstance];
});
return _sharedSingleton;
}
#pragma mark - private method
- (instancetype)initInstance {
return [super init];
}
@end
最后:
只有當一個類表示真正應該存在一次時,才使它成為單例。有些時候,最初看起來符合這個標準的東西將不再適合應用程序的發(fā)展。例如,有多個類型需求,或者是不是生命周期只存在一次。在這種情況下單例方法不再適用。通常,我們會使用manger的管理方式。例如NSFileManager。接下來介紹manger管理方式。