什么是單例模式莲趣?
>是開發(fā)設(shè)計模式(共23種)中的1種
>它可以保證在程序運行過程鸳慈,一個類只有一個實例(一個對象),而且該實例易于供外界訪問喧伞,從而方便地控制了實例個數(shù)走芋,并節(jié)約系統(tǒng)資源
>使用場合:在整個應(yīng)用程序中绩郎,共享一份資源(這份資源只需要創(chuàng)建初始化1次)
iOS系統(tǒng)中的一些單例
UIApplication(應(yīng)用程序?qū)嵗?
NSNotificationCenter(消息中心)
NSFileManager(文件管理)
NSUserDefaults(應(yīng)用程序設(shè)置)
NSURLCache(請求緩存)
NSHTTPCookieStorage(應(yīng)用程序cookies池)
單例模式的基本實現(xiàn)
1.懶漢模式
// 1.在該類中定義一個靜態(tài)的全局變量,防止被外部用extren訪問
staticid_instance;
/**
?static : 修飾變量
?1> 修飾全局變量
?* 全局變量的作用域僅限于當前文件內(nèi)部,其他文件不能用extren關(guān)鍵字訪問
?2> 修飾局部變量 :?
?* 局部變量的生命周期 跟 全局變量 類似
?* 但是不能改變作用域
?* 能保證局部變量永遠只初始化1次翁逞,在程序運行過程中肋杖,永遠只有1分內(nèi)存
?*/
/** * 2.重寫它這個類的llocWithZone:方法,確保只為你這個類分配一次內(nèi)存地址*? alloc方法內(nèi)部會調(diào)用這個方法*/+ (id)allocWithZone:(struct_NSZone *)zone
{
? ? if(_instance == nil) {// 防止頻繁加鎖@synchronized(self) {// 加鎖挖函,避免在多線程中出錯而創(chuàng)建多個對象if(_instance == nil) {// 防止創(chuàng)建多次_instance = [super allocWithZone:zone];
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? return _instance;
}//3.提供一個shared方法讓外界調(diào)用這個單例(一般單例都會提供這個方法)状植,確保只init一次+ (instancetype)sharedMusicTool
{
? ? if(_instance == nil) {// 防止頻繁加鎖? ? ? ? @synchronized(self) {
? ? ? ? ? ? if(_instance == nil) {// 防止創(chuàng)建多次_instance = [[self alloc] init];
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? return _instance;
}// 4.重寫copyWithZone:方法,避免使用copy時創(chuàng)建多個對象- (id)copyWithZone:(NSZone *)zone
{
? ? return _instance;
}
2.餓漢模式(當類加載到OC運行環(huán)境中(內(nèi)存)時怨喘,就會調(diào)用一次生成這個單例(一個類只會加載一次))
// 1.在該類中定義一個靜態(tài)的全局變量,防止被外部用extren訪問staticid _instance;/**
* 2.重寫它這個類的llocWithZone:方法津畸,這里不用加鎖,因為程序剛啟動必怜,線程還沒加載肉拓,不會出現(xiàn)線程不安全的問題
*/+ (id)allocWithZone:(struct_NSZone *)zone
{if(_instance == nil) {// 防止創(chuàng)建多次_instance = [super allocWithZone:zone];
? ? ? ? ? ? }
? ? return _instance;
}// 3.提供一個shared方法讓外界調(diào)用這個單例(一般單例都會提供這個方法)+ (instancetype)sharedMusicTool
{
? ? return _instance;
}// 4.重寫copyWithZone:方法,避免使用copy時創(chuàng)建多個對象- (id)copyWithZone:(NSZone *)zone
{
? ? return _instance;
}// 5.重寫load這個類方法梳庆,在里面alloc它// 這個方法在程序啟動暖途,加載類的時候會調(diào)用一次+ (void)load
{
? _instance = [[self alloc] init];? ? ?
}
用GCD實現(xiàn)單例模式
// 1.staticid _instance;/**
* 2.用GCD的dispatch_once方法重寫
*/+ (id)allocWithZone:(struct_NSZone *)zone
{
? ? static dispatch_once_t onceToken;
? ? dispatch_once(&onceToken, ^{
? ? ? ? _instance = [super allocWithZone:zone];
? ? });
? return _instance;
}// 3.+ (instancetype)sharedMusicTool
{
? ? static dispatch_once_t onceToken;
? ? dispatch_once(&onceToken, ^{
? ? ? ? _instance = [[self alloc] init];
? ? });
? ? return _instance;
}// 4.- (id)copyWithZone:(NSZone *)zone
{
? ? return _instance;
}
非ARC下的單例模式
//前面與ACR一樣,接著重寫以下方法
// 不做release
- (onewayvoid)release {
}// retain之后還是自己一份- (id)retain {
? ? return self;
}// 計數(shù)器永遠為1- (NSUInteger)retainCount {
? ? return1;
}// 防止被放進自動計數(shù)池釋放- (id)autorelease {
? ? return self;
}
用宏定義實現(xiàn)單例(適配ARC和MRC)
//新建一個.h文件或pch文件膏执,把一下代碼copy進去丧肴。在需要實現(xiàn)單例的類中import進去并使用宏(括號里面?zhèn)飨鄳?yīng)的類名)即可
// 在.h文件使用的宏定義#defineHJSingletonH(name) + (instancetype)shared##name;#if__has_feature(objc_arc)// 當前的編譯器環(huán)境是ARC// 在.m文件使用的宏定義#defineHJSingletonM(name) \staticid _instace; \
\+ (id)allocWithZone:(struct_NSZone *)zone \
{ \static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [super allocWithZone:zone]; \
}); \return _instace; \
} \
\+ (instancetype)shared##name \
{ \static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [[self alloc] init]; \
}); \return _instace; \
} \
\- (id)copyWithZone:(NSZone *)zone \
{ \return _instace; \
}#else// 當前的編譯器環(huán)境是MRC// 在.m文件使用的宏定義#defineHJSingletonM(name) \staticid _instace; \
\+ (id)allocWithZone:(struct_NSZone *)zone \
{ \
? ? static dispatch_once_t onceToken; \
? ? dispatch_once(&onceToken, ^{ \
? ? ? ? _instace = [super allocWithZone:zone]; \
? ? }); \
? ? return _instace; \
} \
\+ (instancetype)shared##name \
{ \
? ? static dispatch_once_t onceToken; \
? ? dispatch_once(&onceToken, ^{ \
? ? ? ? _instace = [[self alloc] init]; \
? ? }); \
? ? return _instace; \
} \
\- (id)copyWithZone:(NSZone *)zone \
{ \
? ? return _instace; \
} \- (onewayvoid)release {} \- (id)retain {return self;} \- (NSUInteger)retainCount {return1;} \- (id)autorelease {return self;}#endif