什么是單例模式?
>是開發設計模式(共23種)中的1種
>它可以保證在程序運行過程,一個類只有一個實例(一個對象),而且該實例易于供外界訪問,從而方便地控制了實例個數,并節約系統資源
>使用場合:在整個應用程序中,共享一份資源(這份資源只需要創建初始化1次)
iOS系統中的一些單例
UIApplication(應用程序實例)
NSNotificationCenter(消息中心)
NSFileManager(文件管理)
NSUserDefaults(應用程序設置)
NSURLCache(請求緩存)
NSHTTPCookieStorage(應用程序cookies池)
單例模式的基本實現
1.懶漢模式
// 1.在該類中定義一個靜態的全局變量,防止被外部用extren訪問
staticid_instance;
/**
?static : 修飾變量
?1> 修飾全局變量
?* 全局變量的作用域僅限于當前文件內部,其他文件不能用extren關鍵字訪問
?2> 修飾局部變量 :?
?* 局部變量的生命周期 跟 全局變量 類似
?* 但是不能改變作用域
?* 能保證局部變量永遠只初始化1次,在程序運行過程中,永遠只有1分內存
?*/
/** * 2.重寫它這個類的llocWithZone:方法,確保只為你這個類分配一次內存地址*? alloc方法內部會調用這個方法*/+ (id)allocWithZone:(struct_NSZone *)zone
{
? ? if(_instance == nil) {// 防止頻繁加鎖@synchronized(self) {// 加鎖,避免在多線程中出錯而創建多個對象if(_instance == nil) {// 防止創建多次_instance = [super allocWithZone:zone];
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? return _instance;
}//3.提供一個shared方法讓外界調用這個單例(一般單例都會提供這個方法),確保只init一次+ (instancetype)sharedMusicTool
{
? ? if(_instance == nil) {// 防止頻繁加鎖? ? ? ? @synchronized(self) {
? ? ? ? ? ? if(_instance == nil) {// 防止創建多次_instance = [[self alloc] init];
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? return _instance;
}// 4.重寫copyWithZone:方法,避免使用copy時創建多個對象- (id)copyWithZone:(NSZone *)zone
{
? ? return _instance;
}
2.餓漢模式(當類加載到OC運行環境中(內存)時,就會調用一次生成這個單例(一個類只會加載一次))
// 1.在該類中定義一個靜態的全局變量,防止被外部用extren訪問staticid _instance;/**
* 2.重寫它這個類的llocWithZone:方法,這里不用加鎖,因為程序剛啟動,線程還沒加載,不會出現線程不安全的問題
*/+ (id)allocWithZone:(struct_NSZone *)zone
{if(_instance == nil) {// 防止創建多次_instance = [super allocWithZone:zone];
? ? ? ? ? ? }
? ? return _instance;
}// 3.提供一個shared方法讓外界調用這個單例(一般單例都會提供這個方法)+ (instancetype)sharedMusicTool
{
? ? return _instance;
}// 4.重寫copyWithZone:方法,避免使用copy時創建多個對象- (id)copyWithZone:(NSZone *)zone
{
? ? return _instance;
}// 5.重寫load這個類方法,在里面alloc它// 這個方法在程序啟動,加載類的時候會調用一次+ (void)load
{
? _instance = [[self alloc] init];? ? ?
}
用GCD實現單例模式
// 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;
}// 計數器永遠為1- (NSUInteger)retainCount {
? ? return1;
}// 防止被放進自動計數池釋放- (id)autorelease {
? ? return self;
}
用宏定義實現單例(適配ARC和MRC)
//新建一個.h文件或pch文件,把一下代碼copy進去。在需要實現單例的類中import進去并使用宏(括號里面傳相應的類名)即可
// 在.h文件使用的宏定義#defineHJSingletonH(name) + (instancetype)shared##name;#if__has_feature(objc_arc)// 當前的編譯器環境是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// 當前的編譯器環境是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