iOS單例

在開發(fā)中經(jīng)常會用到單例設(shè)計模式卢肃,目的就是為了在程序的整個生命周期內(nèi)陶珠,只會創(chuàng)建一個類的實例對象,而且只要程序不被殺死徐裸,該實例對象就不會被釋放
在應(yīng)用這個模式時船万,單例對象的類必須保證只有一個實例存在刻撒。許多時候整個系統(tǒng)只需要擁有一個的全局對象,這樣有利于我們協(xié)調(diào)系統(tǒng)整體的行為耿导。比如在APP開發(fā)中我們可能在任何地方都要使用用戶的信息声怔,那么可以在登錄的時候就把用戶信息存放在一個文件里面,這些配置數(shù)據(jù)由一個單例對象統(tǒng)一讀取舱呻,然后服務(wù)進程中的其他對象再通過這個單例對象獲取這些配置信息醋火。這種方式簡化了在復(fù)雜環(huán)境下的配置管理。

創(chuàng)建方式
1.GCD

static id _instance;   
 
+ (instancetype)allocWithZone:(struct _NSZone *)zone  
{   
    static dispatch_once_t onceToken;   
    dispatch_once(&onceToken, ^{   
        _instance = [super allocWithZone:zone];   
    });   
    return _instance;   
}   
 
+ (instancetype)sharedInstance  
{   
    static dispatch_once_t onceToken;   
    dispatch_once(&onceToken, ^{   
        _instance = [[self alloc] init];   
    });   
    return _instance;   
}   
 
- (id)copyWithZone:(NSZone *)zone   
{   
    return _instance;   
}  
 
- (id)mutableCopyWithZone:(NSZone *)zone {   
    return _instance;   
}

2.互斥鎖方式

static id _instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{    @synchronized(self) {        if (_instance == nil) {
            _instance = [super allocWithZone:zone];
        }
    }    return _instance;
}
+ (instancetype)sharedInstance
{    @synchronized(self) {        if (_instance == nil) {
            _instance = [[self alloc] init];
        }
    }    return _instance;
}
- (id)copyWithZone:(NSZone *)zone
{    return _instance;
}

假設(shè)此時有兩條線程:線程1和線程2箱吕,都在調(diào)用shareInstance方法來創(chuàng)建單例芥驳,那么線程1運行到if (_instance == nil)出發(fā)現(xiàn)_instance = nil,那么就會初始化一個_instance,假設(shè)此時線程2也運行到if的判斷處了茬高,此時線程1還沒有創(chuàng)建完成實例_instance兆旬,所以此時_instance = nil還是成立的,那么線程2又會創(chuàng)建一個_instace怎栽。

此時就創(chuàng)建了兩個實例對象丽猬,導(dǎo)致問題宿饱。

解決辦法1、使用dispatch_once
dispatch_once保證程序在運行過程中只會被運行一次宝鼓,那么假設(shè)此時線程1先執(zhí)行shareInstance方法刑棵,創(chuàng)建了一個實例對象,線程2就不會再去執(zhí)行dispatch_once的代碼了愚铡。從而保證了只會創(chuàng)建一個實例對象蛉签。

解決辦法2、使用互斥鎖
假設(shè)此時線程1在執(zhí)行shareInstance方法沥寥,那么synchronize大括號內(nèi)創(chuàng)建單例的代碼碍舍,如下所示:

if (_instance == nil) {
            _instance = [[self alloc] init];
        }

就會被當(dāng)做一個任務(wù)被加上了一把鎖。此時假設(shè)線程2也想執(zhí)行shareInstance方法創(chuàng)建單例邑雅,但是看到了線程1加的互斥鎖片橡,就會進入睡眠模式。等到線程1執(zhí)行完畢淮野,才會被喚醒捧书,然后去執(zhí)行上面所示的創(chuàng)建單例的代碼,但是此時_instance !=nil,所以不會再創(chuàng)建新的實例對象了骤星。從而保證只會創(chuàng)建一個實例對象经瓷。
但是互斥鎖會影響性能,所以最好還是使用GCD方式創(chuàng)建單例洞难。
1 重寫+allocWithZone方法舆吮,保證永遠都只為單例對象分配一次內(nèi)存空間
因為每調(diào)用一次這個方法,就會重新分配一個新的內(nèi)存空間队贱。
2嚴謹起見色冀,重寫-copyWithZone方法和-MutableCopyWithZone方法
為了防止通過copy來創(chuàng)建新的實例我們要重寫copyWithZone MutableCopyWithZone

單例的優(yōu)點:
1.一個類只被實例化一次,提供了對唯一實例的受控訪問
2.節(jié)省系統(tǒng)資源
缺點:
1.一個類只有一個對象柱嫌,可能造成責(zé)任過重锋恬,在一定程度上違背了“單一職責(zé)原則”
2.由于單利模式中沒有抽象層,因此單例類的擴展有很大的困難编丘。
3.濫用單例將帶來一些負面問題与学,如為了節(jié)省資源將數(shù)據(jù)庫連接池對象設(shè)計為的單例類,可能會導(dǎo)致共享連接池對象的程序過多而出現(xiàn)連接池溢出瘪吏;如果實例化的對象長時間不被利用,系統(tǒng)會認為是垃圾而被回收蜗巧,這將導(dǎo)致對象狀態(tài)的丟失掌眠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市幕屹,隨后出現(xiàn)的幾起案子蓝丙,更是在濱河造成了極大的恐慌级遭,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渺尘,死亡現(xiàn)場離奇詭異挫鸽,居然都是意外死亡,警方通過查閱死者的電腦和手機鸥跟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門丢郊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人医咨,你說我怎么就攤上這事枫匾。” “怎么了拟淮?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵干茉,是天一觀的道長。 經(jīng)常有香客問我很泊,道長角虫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任委造,我火速辦了婚禮戳鹅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘争涌。我一直安慰自己粉楚,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布亮垫。 她就那樣靜靜地躺著模软,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饮潦。 梳的紋絲不亂的頭發(fā)上燃异,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天,我揣著相機與錄音继蜡,去河邊找鬼回俐。 笑死,一個胖子當(dāng)著我的面吹牛稀并,可吹牛的內(nèi)容都是我干的仅颇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼碘举,長吁一口氣:“原來是場噩夢啊……” “哼忘瓦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起引颈,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤耕皮,失蹤者是張志新(化名)和其女友劉穎境蜕,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凌停,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡粱年,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了罚拟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片台诗。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖舟舒,靈堂內(nèi)的尸體忽然破棺而出拉庶,到底是詐尸還是另有隱情,我是刑警寧澤秃励,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布氏仗,位于F島的核電站,受9級特大地震影響夺鲜,放射性物質(zhì)發(fā)生泄漏皆尔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一币励、第九天 我趴在偏房一處隱蔽的房頂上張望慷蠕。 院中可真熱鬧,春花似錦食呻、人聲如沸流炕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽每辟。三九已至,卻和暖如春干旧,著一層夾襖步出監(jiān)牢的瞬間渠欺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工椎眯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留挠将,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓编整,卻偏偏與公主長得像舔稀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子掌测,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 在開發(fā)中經(jīng)常會用到單例設(shè)計模式内贮,目的就是為了在程序的整個生命周期內(nèi),只會創(chuàng)建一個類的實例對象,而且只要程序不被殺死...
    零度_不結(jié)冰閱讀 441評論 0 0
  • 單例模式可能是設(shè)計模式中最簡單的形式了贺归,這一模式的意圖就是使得類中的一個對象成為系統(tǒng)中的唯一實例。它提供了對類的對...
    liuyanhongwl閱讀 1,765評論 6 20
  • 在iOS中有很多的設(shè)計模式断箫,有一本書《Elements of Reusable Object-Oriented S...
    鄭明明閱讀 2,386評論 3 26
  • 一拂酣、單例是什么?(apl??ke??(?)n 申請) 在 Foundation 和 Application Kit...
    藍白自由閱讀 6,052評論 6 22
  • 簡介: 單例模式是一種常用的軟件設(shè)計模式仲义。在它的核心結(jié)構(gòu)中只包含一個被稱為單例類的特殊類婶熬。通過單例模式可以保證系統(tǒng)...
    RunnerFL閱讀 634評論 0 0