前文提要:
之前簡友說讓舉栗子,那么今天我們就來舉栗子。
前文傳送門:
iOS設計模式、架構模式、框架簡介之《設計模式簡介》
iOS設計模式之基本規范
單例模式
好了,大家都看到了,單例就是只有一個栗子,為什么只有一個呢。。。。這個嘛.....聽我細細說來。
為什么會需要單例模式這種設計模式呢?當某個對象在整個程序中我們只需要一個,并且我們需要在不同的地方調用這個對象,獲取其中的屬性資源。這種時候我們就需要用到單例模式這種設計模式。比如蘋果的application,以及AFN框架中的AFNetworkReachabilityManager都是單例。我們可以在不同的地方用shared/default方式訪問
[UIApplication sharedApplication]
[AFNetworkReachabilityManager sharedManager]
獲取到對應的單例,并訪問我們需要的資源。
那么我們需要怎么實現單例模式呢?根據需求,我們要保證這個對象能且只能被創建一次,并且我們能在程序的任何地方訪問這個對象。
為了保證單例模式在整個程序中只被創建一次,我們使用GCD 的dispatch_once函數能保證某段代碼在程序運行過程中只被執行1次
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
//使用GCD中的一次性代碼
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
使用加鎖也是可以實現的,看個人愛好。
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
//使用加鎖的方式,保證只分配一次存儲空間
@synchronized(self) {
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
}
return _instance;
}
我們為什么要在allocWithZone:這個方法里面寫實現方法呢?因為使用者可能并不知道你這個是個單例,有可能使用alloc init方式創建對象,而這樣就一定會來到allocWithZone:方法。為了防止其他意外,我們還必須實現以下兩個方法,防止使用者通過其他方式創建。
-(id)copyWithZone:(NSZone *)zone
{
return _instance;
}
-(id)mutableCopyWithZone:(NSZone *)zone
{
return _instance;
}
然后為了我們可以在程序的其他地方獲取他,并且參照iOS設計模式之基本規范;我們將它的API名稱參考蘋果的樣式,
使用:share+類名|default + 類名|share|類名
+(instancetype)sharedFXDGSingle;
+(instancetype)sharedFXDGSingle
{
return [[self alloc]init];
}
在ARC和MRC環境下創建的方式也有所不同。下面給大家提供一個快速創建單例的宏
#define SingleH(name) +(instancetype)shared##name;
//ARC
#if __has_feature(objc_arc)
#define SingleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
+(instancetype)shared##name\
{\
return [[self alloc]init];\
}\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}
#else
//MRC
#define SingleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
+(instancetype)shared##name\
{\
return [[self alloc]init];\
}\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
-(oneway void)release\
{\
}\
\
-(instancetype)retain\
{\
return _instance;\
}\
\
-(NSUInteger)retainCount\
{\
return MAXFLOAT;\
}
#endif
創建好后,就必須根據各自的需求增加屬性了,并提供對應的接口方法。
結語
單例模式是設計模式中最簡單的一個,設計模式主要還是體現的思想,需要在使用中多思考。之前有大神說代碼不超過5W行不要談設計模式,雖然有道理,但是并不贊同。
設計模式本身源于生活,在IT行業出現之前很多領域已經有設計模式的概念,這些本是互通的。代碼再多不去想,也沒用。代碼少,但是有思想一樣可以創建出一個好的設計模式(前提是對編程規則熟悉)。