1.單例模式的要點(diǎn):
顯然單例模式的要點(diǎn)有三個(gè)儒陨;一是某個(gè)類只能有一個(gè)實(shí)例花嘶;二是它必須自行創(chuàng)建這個(gè)實(shí)例;三是它必須自行向整個(gè)系統(tǒng)提供這個(gè)實(shí)例蹦漠。
2.單例模式的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
在內(nèi)存中只有一個(gè)對(duì)象椭员,節(jié)省內(nèi)存空間笛园。
避免頻繁的創(chuàng)建銷毀對(duì)象,可以提高性能埋同。
避免對(duì)共享資源的多重占用凶赁。
可以全局訪問(wèn)逆甜。
缺點(diǎn):
單例對(duì)象一旦建立交煞,對(duì)象指針是保存在靜態(tài)區(qū)的,單例對(duì)象在堆中分配的內(nèi)存空間集嵌,會(huì)在應(yīng)用程序終止后才會(huì)被釋放根欧。
單例類無(wú)法繼承咽块,因此很難進(jìn)行類的擴(kuò)展欺税。
單例不適用于變化的對(duì)象揭璃,如果同一類型的對(duì)象總是要在不同的用例場(chǎng)景發(fā)生變化亭罪,單例就會(huì)引起數(shù)據(jù)的錯(cuò)誤应役,不能保存彼此的狀態(tài)。
2.3適用場(chǎng)景
由于單例模式的以上優(yōu)點(diǎn)院崇,所以是編程中用的比較多的一種設(shè)計(jì)模式底瓣。我總結(jié)了一下我所知道的適合使用單例模式的場(chǎng)景:
需要頻繁實(shí)例化然后銷毀的對(duì)象捐凭。
創(chuàng)建對(duì)象時(shí)耗時(shí)過(guò)多或者耗資源過(guò)多凳鬓,但又經(jīng)常用到的對(duì)象缩举。
有狀態(tài)的工具類對(duì)象。
頻繁訪問(wèn)數(shù)據(jù)庫(kù)或文件的對(duì)象托猩。
以及其他我沒(méi)用過(guò)的所有要求只有一個(gè)對(duì)象的場(chǎng)景站刑。
不要做斷開(kāi)單例類對(duì)象與類中靜態(tài)引用的危險(xiǎn)操作鼻百。
多線程使用單例使用共享資源時(shí)温艇,注意線程安全問(wèn)題勺爱。
2.5 代碼實(shí)例
在IOS中單例模式最常見(jiàn)的只有懶漢模式琐鲁。根據(jù)線程安全的實(shí)現(xiàn)來(lái)區(qū)分,一種是使用@synchronized顾翼,另一種是使用GCD的dispatch_once函數(shù)奈泪。
要實(shí)現(xiàn)單例涝桅,首先需要一個(gè)static的指向類本身的對(duì)象,其次需要一個(gè)初始化類函數(shù)冯遂。下面是兩種實(shí)現(xiàn)的代碼债蜜。
//synchronized方式單例
static SingletonModel *?
+(SingletonModel*)shareInstance
{
@synchronized(self){
if(singleton==nil)?{
singleton?=?[[SingletonModelalloc]init];
}
}
returnsingleton;
}
//GCD方式
+(SingletonModel*)shareInstance
{
staticdispatch_once_t?onceToken;
dispatch_once(&onceToken,^{
singleton?=?[[SingletonModelalloc]init];
});
returnsingleton;
}
總的來(lái)說(shuō)寻定,兩種實(shí)現(xiàn)效果相同,但第二種GCD的實(shí)現(xiàn)方式寫(xiě)起來(lái)比較簡(jiǎn)單琅锻。如果不習(xí)慣GCD的方式恼蓬,可以使用第一種方式僵芹。
2.6 IOS中的單例實(shí)例
在Cocoa Touch中,有:
(1)UIApplication(該類的實(shí)例提供了應(yīng)用程序的集中控制點(diǎn)來(lái)保持應(yīng)用程序的狀態(tài))荷辕;
(2)UIAccelerometer(該類可以訪問(wèn)重力加速計(jì)硬件設(shè)備)疮方;
(3)NSUserDefault(可以方便讀取應(yīng)用設(shè)置數(shù)據(jù)骡显,用來(lái)是持久化數(shù)據(jù)的);
(4)NSNotificationCenter(采用觀察者模式提供信息廣播通知的通知中心類)等單例類壁顶。
Cocoa框架中也有兩個(gè)常見(jiàn)的類:
(1)NSFileManger(提供了訪問(wèn)文件系統(tǒng)的通用操作)博助;
(2)NSBundle(提供了動(dòng)態(tài)加載或者卸載的可執(zhí)行代碼痹愚,定位資源文件以及資源本地化,訪問(wèn)文件系統(tǒng)等功能)類窖式。
二. 單例在ARC中的實(shí)現(xiàn)
ARC中單例實(shí)現(xiàn)步驟
1 在類的內(nèi)部提供一個(gè)static修飾的全局變量
2 提供一個(gè)類方法萝喘,方便外界訪問(wèn)
3 重寫(xiě)+allocWithZone方法阁簸,保證永遠(yuǎn)都只為單例對(duì)象分配一次內(nèi)存空間
4 嚴(yán)謹(jǐn)起見(jiàn)哼丈,重寫(xiě)-copyWithZone方法和-MutableCopyWithZone方法
ARC中單例代碼實(shí)現(xiàn)
#import "Tools.h"
@implementation Tools
// 創(chuàng)建靜態(tài)對(duì)象 防止外部訪問(wèn)
static Tools *_instance;
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
//? ? @synchronized (self) {
//? ? ? ? // 為了防止多線程同時(shí)訪問(wèn)對(duì)象醉旦,造成多次分配內(nèi)存空間车胡,所以要加上線程鎖
//? ? ? ? if (_instance == nil) {
//? ? ? ? ? ? _instance = [super allocWithZone:zone];
//? ? ? ? }
//? ? ? ? return _instance;
//? ? }
// 也可以使用一次性代碼
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
});
return _instance;
}
// 為了使實(shí)例易于外界訪問(wèn) 我們一般提供一個(gè)類方法
// 類方法命名規(guī)范 share類名|default類名|類名
+(instancetype)shareTools
{
//return _instance;
// 最好用self 用Tools他的子類調(diào)用時(shí)會(huì)出現(xiàn)錯(cuò)誤
return [[self alloc]init];
}
// 為了嚴(yán)謹(jǐn)匈棘,也要重寫(xiě)copyWithZone 和 mutableCopyWithZone
-(id)copyWithZone:(NSZone *)zone
{
return _instance;
}
-(id)mutableCopyWithZone:(NSZone *)zone
{
return _instance;
}