單例模式
一個類在整個系統(tǒng)中有且僅有一個實例。
單例模式的作用
可以保證在程序運行過程中,一個類只有一個實例,而且該實例易于被外界訪問。單例模式控制了實例個數(shù),從而節(jié)約系統(tǒng)資源。
單例模式的使用場合
在整個應(yīng)用程序中,共享一份資源(這份資源只需要創(chuàng)建初始化 1 次),一般用于工具類。例如:登陸控制器,網(wǎng)絡(luò)數(shù)據(jù)請求,音樂播放器等一個工程需要使用多次的控制器或方法。iOS 中 UIApplication、NSFileManager、NSUserDefaults 等都是單例模式。
優(yōu)點:
對實例個數(shù)進行控制,節(jié)約系統(tǒng)資源。
如果希望在系統(tǒng)中某個類的對象只能存在一個,單例模式是最好的解決方案。
單例模式中,因為類控制了實例化過程,所以類可以更加靈活修改實例化過程。
缺點:
單例對象一旦建立,對象指針是保存在靜態(tài)區(qū)的。單例對象在堆中分配的內(nèi)存空間,會在應(yīng)用程序終止后才會被釋放。
單例類無法繼承,因此很難進行類的擴展。
單例不適用于變化的對象,如果同一類型的對象在不同的場景總是發(fā)生變化,單例就會引起數(shù)據(jù)的錯誤,不能保存彼此的狀態(tài)。
單例模式的實現(xiàn)方式
1.第一種方式,重寫+allocWithZone:方法:
+(instancetype)allocWithZone:(struct _NSZone *)zone{
static id instance = nil;
@synchronized (self) { //為了線程安全,加上互斥鎖
if (instance == nil) {
instance = [super allocWithZone:zone];
}
}
return instance;
}
2.第二種方式,不用重寫+allocWithZone:方法,而是直接用@synchronized 來保證線程安全,其它與上面這個方法一樣
+(instancetype)shareInstance{
static id instance = nil;
//用@synchronized 來保證線程安全
@synchronized (self) {
if (instance == nil) {
instance = [[self alloc] init];
}
}
return instance;
}
3.通過 GCD 的 dispatch_once 來實現(xiàn)單例,同樣可以在保證線程安全的前提下來實現(xiàn)單例
+(instancetype)sharedGCDSingleton{
static id instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
注意
為了防止別人不小心利用 alloc/init 方式創(chuàng)建示例,也為了防止別人故意為之,我們要保證不管用什么方式創(chuàng)建都只能是同一個實例對象,這就得重寫 alloc 方法,實現(xiàn)如下:
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}