簡(jiǎn)介:
單例模式是一種常用的軟件設(shè)計(jì)模式俯渤。在它的核心結(jié)構(gòu)中只包含一個(gè)被稱為單例類的特殊類挚躯。通過(guò)單例模式可以保證系統(tǒng)中一個(gè)類只有一個(gè)實(shí)例而且該實(shí)例易于外界訪問(wèn)袁勺。
單例模式三要素:
1.該類有且只有一個(gè)實(shí)例;
2.該類必須能夠自行創(chuàng)建這個(gè)實(shí)例;
3.該類必須能夠自行向整個(gè)系統(tǒng)提====供這個(gè)實(shí)例灶芝。
作用:
1.如果說(shuō)創(chuàng)建一個(gè)對(duì)象會(huì)耗費(fèi)很多系統(tǒng)資源,那么此時(shí)采用單例模式漓藕,因?yàn)橹恍枰粋€(gè)實(shí)例,會(huì)節(jié)省alloc的時(shí)間
2.在IOS開(kāi)發(fā)中挟裂,如果很多模塊都要使用同一個(gè)變量撵术,此時(shí)如果把該變量放入單例類,則所有訪問(wèn)該變量的調(diào)用變得很容易话瞧,否則嫩与,只能通過(guò)一個(gè)模塊傳遞給另外一個(gè)模塊,這樣增加了風(fēng)險(xiǎn)和復(fù)雜度
優(yōu)點(diǎn):
1交排、提供了對(duì)唯一實(shí)例的受控訪問(wèn)划滋。
2、由于在系統(tǒng)內(nèi)存中只存在一個(gè)對(duì)象埃篓,因此可以節(jié)約系統(tǒng)資源处坪,對(duì)于一些需要頻繁創(chuàng)建和銷毀的對(duì)象單例模式無(wú)疑可以提高系統(tǒng)的性能。
3架专、允許可變數(shù)目的實(shí)例同窘。
缺點(diǎn):
1、由于單利模式中沒(méi)有抽象層部脚,因此單例類的擴(kuò)展有很大的困難想邦。
2、單例類的職責(zé)過(guò)重委刘,在一定程度上違背了“單一職責(zé)原則”丧没。
3、濫用單例將帶來(lái)一些負(fù)面問(wèn)題锡移,如為了節(jié)省資源將數(shù)據(jù)庫(kù)連接池對(duì)象設(shè)計(jì)為的單例類呕童,可能會(huì)導(dǎo)致共享連接池對(duì)象的程序過(guò)多而出現(xiàn)連接池溢出;如果實(shí)例化的對(duì)象長(zhǎng)時(shí)間不被利用淆珊,系統(tǒng)會(huì)認(rèn)為是垃圾而被回收夺饲,這將導(dǎo)致對(duì)象狀態(tài)的丟失。
應(yīng)用場(chǎng)景:
整個(gè)程序共用一份資源時(shí)(我們只需要對(duì)這份資源初始化一次)可以使用單例
例如:
1.設(shè)置單例類訪問(wèn)應(yīng)用的配置信息、
2.用戶的個(gè)人信息登陸后用nsuserdefaults 存儲(chǔ)往声,對(duì)登錄類進(jìn)一步采用單例封裝方便全局訪問(wèn)
3.封裝一個(gè)單例對(duì)應(yīng)用多處對(duì)同一本地?cái)?shù)據(jù)庫(kù)進(jìn)行操作
代碼示例
在objective-c中要實(shí)現(xiàn)一個(gè)單例類茫蛹,至少需要做以下四個(gè)步驟:
1、為單例對(duì)象實(shí)現(xiàn)一個(gè)靜態(tài)實(shí)例烁挟,并初始化婴洼,然后設(shè)置成nil,
2撼嗓、實(shí)現(xiàn)一個(gè)實(shí)例構(gòu)造方法檢查上面聲明的靜態(tài)實(shí)例是否為nil柬采,如果是則新建并返回一個(gè)本類的實(shí)例,
3且警、重寫(xiě)allocWithZone方法粉捻,用來(lái)保證其他人直接使用alloc和init試圖獲得一個(gè)新實(shí)力的時(shí)候不產(chǎn)生一個(gè)新實(shí)例,
4斑芜、適當(dāng)實(shí)現(xiàn)copyWithZone(mrc還需要實(shí)現(xiàn)以下內(nèi)存管理方法)
- (id)retain { return self; }
- (NSUInteger)retainCount { return 1; }
- (oneway void)release {}
- (id)autorelease { return self; }
以下為實(shí)現(xiàn)單例的兩種常用方式:
```
單例模式- ARC -方法一
ARC中單例模式的實(shí)現(xiàn)
在 .m中保留一個(gè)全局的static的實(shí)例
staticid_instance;
//重寫(xiě)allocWithZone:方法肩刃,在這里創(chuàng)建唯一的實(shí)例(注意線程安全)
+ (instancetype)allocWithZone:(struct_NSZone*)zone
{
@synchronized(self)
{
if(_instance ==nil)
{? ? ? ??
? _instance = [super allocWithZone:zone];? ? ?
? }? ?
}
return_instance;
}
提供1個(gè)類方法讓外界訪問(wèn)唯一的實(shí)例
+ (instancetype)sharedInstanceTool
{
@synchronized(self)
{
if (_instance ==nil)
{? ? ? ??
? ?? _instance = [[self alloc] init];? ? ?
? }
? }
return_instance;
}
實(shí)現(xiàn)copyWithZone:方法
-(id)copyWithZone:(struct_NSZone*)zone{return_instance;? }
我們?cè)趕haredInstanceTool,首先檢查類的唯一實(shí)例是否已經(jīng)創(chuàng)建杏头,如果就會(huì)創(chuàng)建實(shí)例并將其返回盈包。而之所以調(diào)用super而不是self,是因?yàn)橐呀?jīng)在self中重載了基本的對(duì)象分配的方法醇王,需要借用父類的功能來(lái)幫助處理底層內(nèi)存的分配呢燥。
在allocWithZone:(struct _NSZone*)zone方法中,只是返回從sharedInstanceTool方法返回的類實(shí)例寓娩。而同樣的在Cocoa框架中調(diào)用allocWithZone:(struct _NSZone*)zone會(huì)分配內(nèi)存叛氨,引用計(jì)數(shù)會(huì)設(shè)置為1,然后返回實(shí)例棘伴。同樣的重寫(xiě)(id)copyWithZone:(struct _NSZone *)zone方法寞埠,也是為了保證不會(huì)返回實(shí)例的副本,而是返回self.返回同一個(gè)實(shí)例焊夸。
```
方法二
```
#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
```