03-單例模式

單例模式-Singleton Pattern是 Java 中最簡單的設(shè)計(jì)模式之一芹壕。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式拉背,它提供了一種創(chuàng)建對象的最佳方式断箫」辖【學(xué)習(xí)難度:★☆☆☆☆,使用頻率:★★★★☆】

確保對象的唯一性——單例模式 (一):單例模式的動(dòng)機(jī)比原,單例模式概述
確保對象的唯一性——單例模式 (二):負(fù)載均衡器的設(shè)計(jì)與實(shí)現(xiàn)
確保對象的唯一性——單例模式 (三):餓漢式單例與懶漢式單例的討論
確保對象的唯一性——單例模式 (四):一種更好的單例實(shí)現(xiàn)方法(靜態(tài)內(nèi)部類)
確保對象的唯一性——單例模式 (五):單例模式總結(jié)

這種模式涉及到一個(gè)單一的類插佛,該類負(fù)責(zé)創(chuàng)建自己的對象,同時(shí)確保只有單個(gè)對象被創(chuàng)建量窘。這個(gè)類提供了一種訪問其唯一的對象的方式雇寇,可以直接訪問,不需要實(shí)例化該類的對象蚌铜。

注意:
1锨侯、單例類只能有一個(gè)實(shí)例。
2冬殃、單例類必須自己創(chuàng)建自己的唯一實(shí)例囚痴。
3、單例類必須給所有其他對象提供這一實(shí)例审葬。

介紹
意圖:保證一個(gè)類僅有一個(gè)實(shí)例深滚,并提供一個(gè)訪問它的全局訪問點(diǎn)。
主要解決:一個(gè)全局使用的類頻繁地創(chuàng)建與銷毀耳璧。
何時(shí)使用:當(dāng)您想控制實(shí)例數(shù)目成箫,節(jié)省系統(tǒng)資源的時(shí)候。
如何解決:判斷系統(tǒng)是否已經(jīng)有這個(gè)單例旨枯,如果有則返回蹬昌,如果沒有則創(chuàng)建。
關(guān)鍵代碼:構(gòu)造函數(shù)是私有的攀隔。

應(yīng)用實(shí)例:
1皂贩、一個(gè)黨只能有一個(gè)主席。
2昆汹、Windows 是多進(jìn)程多線程的明刷,在操作一個(gè)文件的時(shí)候,就不可避免地出現(xiàn)多個(gè)進(jìn)程或線程同時(shí)操作一個(gè)文件的現(xiàn)象满粗,所以所有文件的處理必須通過唯一的實(shí)例來進(jìn)行辈末。
3、一些設(shè)備管理器常常設(shè)計(jì)為單例模式映皆,比如一個(gè)電腦有兩臺打印機(jī)挤聘,在輸出的時(shí)候就要處理不能兩臺打印機(jī)打印同一個(gè)文件。

優(yōu)點(diǎn):
1捅彻、在內(nèi)存里只有一個(gè)實(shí)例组去,減少了內(nèi)存的開銷,尤其是頻繁的創(chuàng)建和銷毀實(shí)例(比如管理學(xué)院首頁頁面緩存)步淹。
2从隆、避免對資源的多重占用(比如寫文件操作)诚撵。

缺點(diǎn):
沒有接口,不能繼承键闺,與單一職責(zé)原則沖突寿烟,一個(gè)類應(yīng)該只關(guān)心內(nèi)部邏輯,而不關(guān)心外面怎么樣來實(shí)例化艾杏。

使用場景:
1韧衣、要求生產(chǎn)唯一序列號。
2购桑、WEB 中的計(jì)數(shù)器,不用每次刷新都在數(shù)據(jù)庫里加一次氏淑,用單例先緩存起來勃蜘。
3、創(chuàng)建的一個(gè)對象需要消耗的資源過多假残,比如 I/O 與數(shù)據(jù)庫的連接等缭贡。

注意事項(xiàng):getInstance() 方法中需要使用同步鎖 synchronized (Singleton.class) 防止多線程同時(shí)進(jìn)入造成 instance 被多次實(shí)例化。


iOS中的單例模式:

ARC中單例實(shí)現(xiàn)步驟

1 在類的內(nèi)部提供一個(gè)static修飾的全局變量
2 提供一個(gè)類方法辉懒,方便外界訪問
3 重寫+allocWithZone方法阳惹,保證永遠(yuǎn)都只為單例對象分配一次內(nèi)存空間
4 嚴(yán)謹(jǐn)起見,重寫-copyWithZone方法和-MutableCopyWithZone方法

#import "Tools.h"

@implementation Tools
// 創(chuàng)建靜態(tài)對象 防止外部訪問
static Tools *_instance;
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
//    @synchronized (self) {
//        // 為了防止多線程同時(shí)訪問對象眶俩,造成多次分配內(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í)例易于外界訪問 我們一般提供一個(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),也要重寫copyWithZone 和 mutableCopyWithZone
-(id)copyWithZone:(NSZone *)zone
{
    return _instance;
}
-(id)mutableCopyWithZone:(NSZone *)zone
{
    return _instance;
}

MRC單例實(shí)現(xiàn)步驟

1 在類的內(nèi)部提供一個(gè)static修飾的全局變量
2 提供一個(gè)類方法颠印,方便外界訪問
3 重寫+allocWithZone方法纲岭,保證永遠(yuǎn)都只為單例對象分配一次內(nèi)存空間
4 嚴(yán)謹(jǐn)起見,重寫-copyWithZone方法和-MutableCopyWithZone方法
5 重寫release方法
6 重寫retain方法
7 建議在retainCount方法中返回一個(gè)最大值

配置MRC環(huán)境

1 注意ARC不是垃圾回收機(jī)制线罕,是編譯器特性
2 配置MRC環(huán)境:build setting ->搜索automatic ref->修改為N0

-(oneway void)release
{
    
}
-(instancetype)retain
{
    return _instance;
}
-(NSUInteger)retainCount
{
    return MAXFLOAT;
}

一勞永逸止潮,單例模式的優(yōu)化
如果想要一勞永逸,我們將面臨兩個(gè)問題
1:如何寫一份單例代碼在ARC和MRC環(huán)境下都適用钞楼?
2:如何使一份單例代碼可以多個(gè)類共同使用
為了解決這兩個(gè)問題喇闸,我們可以在PCH文件使用代參數(shù)的宏和條件編譯
利用條件編譯來判斷是ARC還是MRC環(huán)境

#if __has_feature(objc_arc)
//如果是ARC,那么就執(zhí)行這里的代碼1
#else
//如果不是ARC询件,那么就執(zhí)行代理的代碼2
#endif

注意:單例模式不可以使用繼承燃乍,因?yàn)槭褂美^承,同時(shí)也會(huì)繼承靜態(tài)變量雳殊,當(dāng)子類和父類同時(shí)創(chuàng)建的時(shí)候只會(huì)創(chuàng)建一個(gè)先創(chuàng)建的實(shí)例對象橘沥。
Single.h文件

#define singleH(name) +(instancetype)share##name;

#if __has_feature(objc_arc)

#define singleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
        _instance = [super allocWithZone:zone];\
    });\
    return _instance;\
}\
\
+(instancetype)share##name\
{\
    return [[self alloc]init];\
}\
-(id)copyWithZone:(NSZone *)zone\
{\
    return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
    return _instance;\
}
#else
#define singleM static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
\
+(instancetype)shareTools\
{\
return [[self alloc]init];\
}\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
-(oneway void)release\
{\
}\
\
-(instancetype)retain\
{\
    return _instance;\
}\
\
-(NSUInteger)retainCount\
{\
    return MAXFLOAT;\
}
#endif

用法:
在.h文件中調(diào)用singleH(類名)
在.m文件中調(diào)用singleM(類名)
創(chuàng)建類時(shí)直接調(diào)用share類名方法即可。

單例模式中夯秃,為什么用 static 修飾 dispatch_once_t座咆?

比如:

+ (instancetype)sharedManager
{
    static PhotoManager *sharedPhotoManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [NSThread sleepForTimeInterval:2];
        sharedPhotoManager = [[PhotoManager alloc] init];
        NSLog(@"Singleton has memory address at: %@", sharedPhotoManager);
        [NSThread sleepForTimeInterval:2];
        sharedPhotoManager->_photosArray = [NSMutableArray array];
    });
    return sharedPhotoManager;
}

這里有:

static PhotoManager *sharedPhotoManager = nil;
static dispatch_once_t onceToken;

為何用static修飾痢艺?不用staitc有何影響?
答:靜態(tài)局部變量介陶,雖然作用域沒變堤舒,但是可以整個(gè)程序生命周期都保持不被銷毀。

參考文章:
iOS-單例模式寫一次就夠了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哺呜,一起剝皮案震驚了整個(gè)濱河市舌缤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌某残,老刑警劉巖国撵,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異玻墅,居然都是意外死亡介牙,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門澳厢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來环础,“玉大人,你說我怎么就攤上這事剩拢∠叩茫” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵徐伐,是天一觀的道長贯钩。 經(jīng)常有香客問我,道長呵晨,這世上最難降的妖魔是什么魏保? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮摸屠,結(jié)果婚禮上谓罗,老公的妹妹穿的比我還像新娘。我一直安慰自己季二,他們只是感情好檩咱,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著胯舷,像睡著了一般刻蚯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上桑嘶,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天炊汹,我揣著相機(jī)與錄音,去河邊找鬼逃顶。 笑死讨便,一個(gè)胖子當(dāng)著我的面吹牛充甚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播霸褒,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼伴找,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了废菱?” 一聲冷哼從身側(cè)響起技矮,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎殊轴,沒想到半個(gè)月后衰倦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡旁理,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年耿币,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片韧拒。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖十性,靈堂內(nèi)的尸體忽然破棺而出叛溢,到底是詐尸還是另有隱情,我是刑警寧澤劲适,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布楷掉,位于F島的核電站,受9級特大地震影響霞势,放射性物質(zhì)發(fā)生泄漏烹植。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一愕贡、第九天 我趴在偏房一處隱蔽的房頂上張望草雕。 院中可真熱鬧,春花似錦固以、人聲如沸墩虹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诫钓。三九已至,卻和暖如春篙螟,著一層夾襖步出監(jiān)牢的瞬間菌湃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工遍略, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惧所,地道東北人骤坐。 一個(gè)月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像纯路,于是被迫代替她去往敵國和親或油。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

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

  • (1)單例模式 在程序運(yùn)行過程驰唬,一個(gè)類只有一個(gè)實(shí)例 (2)使用場合 在整個(gè)應(yīng)用程序中顶岸,共享一份資源(這份資源只需要...
    奧斯卡先生閱讀 329評論 1 0
  • 一. 單例模式簡介 單例模式的作用可以保證在程序運(yùn)行過程,一個(gè)類只有一個(gè)實(shí)例叫编,而且該實(shí)例易于供外界訪問從而方便地控...
    xx_cc閱讀 50,228評論 15 146
  • 原鏈接:http://www.reibang.com/p/4867dc92337e原作者:僅供我個(gè)人收藏學(xué)習(xí)辖佣,原博...
    油菜花花花花閱讀 333評論 0 0
  • 單例模式作用 可以保證在程序運(yùn)行過程中,一個(gè)類只有一個(gè)實(shí)例搓逾,而且該實(shí)例易于供外界使用 從而方便地控制了實(shí)例個(gè)數(shù)卷谈,并...
    珍此良辰閱讀 1,320評論 3 8
  • 單例模式的作用:可以保證在程序運(yùn)行過程,一個(gè)類只有一個(gè)實(shí)例霞篡,而且該實(shí)例易于供外界訪問世蔗,從而方便地控制了實(shí)例個(gè)數(shù),并...
    BEYOND黃閱讀 286評論 0 3