單例模式
一個(gè)類在整個(gè)系統(tǒng)中有且僅有一個(gè)實(shí)例得滤。
單例模式的作用
可以保證在程序運(yùn)行過程中,一個(gè)類只有一個(gè)實(shí)例盒犹,而且該實(shí)例易于被外界訪問懂更。單例模式控制了實(shí)例個(gè)數(shù),從而節(jié)約系統(tǒng)資源急膀。
單例模式的使用場合
在整個(gè)應(yīng)用程序中沮协,共享一份資源(這份資源只需要?jiǎng)?chuàng)建初始化 1 次),一般用于工具類卓嫂。例如:登陸控制器慷暂,網(wǎng)絡(luò)數(shù)據(jù)請求,音樂播放器等一個(gè)工程需要使用多次的控制器或方法晨雳。iOS 中 UIApplication行瑞、NSFileManager、NSUserDefaults 等都是單例模式餐禁。
優(yōu)點(diǎn):
對實(shí)例個(gè)數(shù)進(jìn)行控制血久,節(jié)約系統(tǒng)資源。
如果希望在系統(tǒng)中某個(gè)類的對象只能存在一個(gè)帮非,單例模式是最好的解決方案氧吐。
單例模式中讹蘑,因?yàn)轭惪刂屏藢?shí)例化過程,所以類可以更加靈活修改實(shí)例化過程筑舅。
缺點(diǎn):
單例對象一旦建立座慰,對象指針是保存在靜態(tài)區(qū)的。單例對象在堆中分配的內(nèi)存空間豁翎,會(huì)在應(yīng)用程序終止后才會(huì)被釋放角骤。
單例類無法繼承,因此很難進(jìn)行類的擴(kuò)展心剥。
單例不適用于變化的對象,如果同一類型的對象在不同的場景總是發(fā)生變化背桐,單例就會(huì)引起數(shù)據(jù)的錯(cuò)誤优烧,不能保存彼此的狀態(tài)。
單例模式的實(shí)現(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 來保證線程安全,其它與上面這個(gè)方法一樣
+(instancetype)shareInstance{
static id instance = nil;
//用@synchronized 來保證線程安全
@synchronized (self) {
if (instance == nil) {
instance = [[self alloc] init];
}
}
return instance;
}
3.通過 GCD 的 dispatch_once 來實(shí)現(xiàn)單例,同樣可以在保證線程安全的前提下來實(shí)現(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)建都只能是同一個(gè)實(shí)例對象,這就得重寫 alloc 方法弊仪,實(shí)現(xiàn)如下:
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}