簡介:
單例模式是一種常用的軟件設計模式。在它的核心結構中只包含一個被稱為單例類的特殊類。通過單例模式可以保證系統中一個類只有一個實例而且該實例易于外界訪問。
單例模式三要素:
1.該類有且只有一個實例;
2.該類必須能夠自行創建這個實例;
3.該類必須能夠自行向整個系統提====供這個實例。
作用:
1.如果說創建一個對象會耗費很多系統資源,那么此時采用單例模式,因為只需要一個實例,會節省alloc的時間
2.在IOS開發中,如果很多模塊都要使用同一個變量,此時如果把該變量放入單例類,則所有訪問該變量的調用變得很容易,否則,只能通過一個模塊傳遞給另外一個模塊,這樣增加了風險和復雜度
優點:
1、提供了對唯一實例的受控訪問。
2、由于在系統內存中只存在一個對象,因此可以節約系統資源,對于一些需要頻繁創建和銷毀的對象單例模式無疑可以提高系統的性能。
3、允許可變數目的實例。
缺點:
1、由于單利模式中沒有抽象層,因此單例類的擴展有很大的困難。
2、單例類的職責過重,在一定程度上違背了“單一職責原則”。
3、濫用單例將帶來一些負面問題,如為了節省資源將數據庫連接池對象設計為的單例類,可能會導致共享連接池對象的程序過多而出現連接池溢出;如果實例化的對象長時間不被利用,系統會認為是垃圾而被回收,這將導致對象狀態的丟失。
應用場景:
整個程序共用一份資源時(我們只需要對這份資源初始化一次)可以使用單例
例如:
1.設置單例類訪問應用的配置信息、
2.用戶的個人信息登陸后用nsuserdefaults 存儲,對登錄類進一步采用單例封裝方便全局訪問
3.封裝一個單例對應用多處對同一本地數據庫進行操作
代碼示例
在objective-c中要實現一個單例類,至少需要做以下四個步驟:
1、為單例對象實現一個靜態實例,并初始化,然后設置成nil,
2、實現一個實例構造方法檢查上面聲明的靜態實例是否為nil,如果是則新建并返回一個本類的實例,
3、重寫allocWithZone方法,用來保證其他人直接使用alloc和init試圖獲得一個新實力的時候不產生一個新實例,
4、適當實現copyWithZone(mrc還需要實現以下內存管理方法)
- (id)retain { return self; }
- (NSUInteger)retainCount { return 1; }
- (oneway void)release {}
- (id)autorelease { return self; }
以下為實現單例的兩種常用方式:
```
單例模式- ARC -方法一
ARC中單例模式的實現
在 .m中保留一個全局的static的實例
staticid_instance;
//重寫allocWithZone:方法,在這里創建唯一的實例(注意線程安全)
+ (instancetype)allocWithZone:(struct_NSZone*)zone
{
@synchronized(self)
{
if(_instance ==nil)
{? ? ? ??
? _instance = [super allocWithZone:zone];? ? ?
? }? ?
}
return_instance;
}
提供1個類方法讓外界訪問唯一的實例
+ (instancetype)sharedInstanceTool
{
@synchronized(self)
{
if (_instance ==nil)
{? ? ? ??
? ?? _instance = [[self alloc] init];? ? ?
? }
? }
return_instance;
}
實現copyWithZone:方法
-(id)copyWithZone:(struct_NSZone*)zone{return_instance;? }
我們在sharedInstanceTool,首先檢查類的唯一實例是否已經創建,如果就會創建實例并將其返回。而之所以調用super而不是self,是因為已經在self中重載了基本的對象分配的方法,需要借用父類的功能來幫助處理底層內存的分配。
在allocWithZone:(struct _NSZone*)zone方法中,只是返回從sharedInstanceTool方法返回的類實例。而同樣的在Cocoa框架中調用allocWithZone:(struct _NSZone*)zone會分配內存,引用計數會設置為1,然后返回實例。同樣的重寫(id)copyWithZone:(struct _NSZone *)zone方法,也是為了保證不會返回實例的副本,而是返回self.返回同一個實例。
```
方法二
```
#import"Singleton.h"
@implementationSingleton
staticSingleton* _instance = nil;
+(instancetype)shareInstance
{
static dispatch_once_t onceToken ;
dispatch_once(&onceToken, ^{
_instance = [[super allocWithZone:NULL]init] ;
}) ;
return_instance ;
}
+(id)allocWithZone:(struct _NSZone *)zone
{
return [Singleton shareInstance] ;
}
-(id)copyWithZone:(struct _NSZone *)zone
{
return [Singleton shareInstance] ;
}
@end
```