單例模式的理解

  • 單例的作用 :
    個(gè)人的理解就是內(nèi)存地址只分配一次,不管你是在主線程調(diào)用還是在子線程調(diào)用择克,方便我們使用的某個(gè)對(duì)象 恬总。比如 登陸的用戶模型 你可能用戶名 昵稱等等的隨時(shí)都在用 但是呢又沒(méi)有必要持久化存儲(chǔ)的這個(gè)時(shí)候可能用到單例。
  • 單例的模式 :懶漢是單例
    解釋:顧名思義 就是我們用到的時(shí)候才會(huì)加載肚邢,其實(shí)我們平時(shí)也很多時(shí)候用到壹堰。
    代碼:
// 1.在該類中定義一個(gè)靜態(tài)的全局變量,防止被外部用extren訪問(wèn)
static id _instance;
/**

 static : 修飾變量

 1> 修飾全局變量

 * 全局變量的作用域僅限于當(dāng)前文件內(nèi)部拭卿,其他文件不能用extren關(guān)鍵字訪問(wèn)

 2> 修飾局部變量 : 

 * 局部變量的生命周期 跟 全局變量 類似

 * 但是不能改變作用域

 * 能保證局部變量永遠(yuǎn)只初始化1次,在程序運(yùn)行過(guò)程中贱纠,永遠(yuǎn)只有1分內(nèi)存

 */

 
/**
 * 2.重寫它這個(gè)類的llocWithZone:方法峻厚,確保只為你這個(gè)類分配一次內(nèi)存地址
 *  alloc方法內(nèi)部會(huì)調(diào)用這個(gè)方法
 */
+ (id)allocWithZone:(struct _NSZone *)zone
{
    if (_instance == nil) { // 防止頻繁加鎖
        @synchronized(self) { // 加鎖,避免在多線程中出錯(cuò)而創(chuàng)建多個(gè)對(duì)象
            if (_instance == nil) { // 防止創(chuàng)建多次
                _instance = [super allocWithZone:zone]; 
            }
        }
    }
    return _instance;
}

// 3.提供一個(gè)shared方法讓外界調(diào)用這個(gè)單例(一般單例都會(huì)提供這個(gè)方法)谆焊,確保只init一次
+ (instancetype)sharedMusicTool
{
    if (_instance == nil) { // 防止頻繁加鎖
        @synchronized(self) {
            if (_instance == nil) { // 防止創(chuàng)建多次
                _instance = [[self alloc] init];
            }
        }
    }
    return _instance;
}

// 4.重寫copyWithZone:方法惠桃,避免使用copy時(shí)創(chuàng)建多個(gè)對(duì)象
- (id)copyWithZone:(NSZone *)zone
{
    return _instance;
}

解釋:其實(shí)要將寫好點(diǎn) 我們還需要實(shí)現(xiàn)他的mutablecopy 方法,為什么枷鎖 就是防止多線程出錯(cuò)從而不是創(chuàng)建不是一次

  • 單例之餓漢式加載
    自己的理解:就是當(dāng)加載的oc運(yùn)行環(huán)境時(shí)加載一次懊渡,每個(gè)類只是加載一次刽射,這個(gè)我們平時(shí)不常用,但是作為一個(gè)程序員 我們有必要深究并且知道為什么剃执。
    代碼:
// 1.在該類中定義一個(gè)靜態(tài)的全局變量,防止被外部用extren訪問(wèn)
static id _instance;

/**
 * 2.重寫它這個(gè)類的llocWithZone:方法誓禁,這里不用加鎖,因?yàn)槌绦騽倖?dòng)肾档,線程還沒(méi)加載摹恰,不會(huì)出現(xiàn)線程不安全的問(wèn)題
 */
+ (id)allocWithZone:(struct _NSZone *)zone
{
            if (_instance == nil) { // 防止創(chuàng)建多次
                _instance = [super allocWithZone:zone];
            }
    return _instance;
}

// 3.提供一個(gè)shared方法讓外界調(diào)用這個(gè)單例(一般單例都會(huì)提供這個(gè)方法)
+ (instancetype)sharedMusicTool
{
    return _instance;
}

// 4.重寫copyWithZone:方法,避免使用copy時(shí)創(chuàng)建多個(gè)對(duì)象
- (id)copyWithZone:(NSZone *)zone
{
    return _instance;
}

// 5.重寫load這個(gè)類方法怒见,在里面alloc它
// 這個(gè)方法在程序啟動(dòng)俗慈,加載類的時(shí)候會(huì)調(diào)用一次
+ (void)load
{
  _instance = [[self alloc] init];      
}

解釋:這里不用枷鎖 沒(méi)事的 因?yàn)槌绦騽倖?dòng)線程還沒(méi)有加載 所用不用枷鎖 為了更加安全 枷鎖更好了。

  • 單例模式- 在MRC情況下:
    說(shuō)明:我剛開(kāi)始學(xué)習(xí)ios的時(shí)候 那時(shí)候xcode還是5 現(xiàn)在都xocde9了 幾乎所有的公司都是ARC了遣耍,所以這個(gè)我們可以不用多管 但是必須的得知道闺阱,下面我會(huì)在下面用一個(gè)宏說(shuō)明
  • 單例模式-gcd的方式
    解釋:我們主要用到的是gcd的方式 不再用枷鎖的方式 因?yàn)槲覀€(gè)人覺(jué)得系統(tǒng)在內(nèi)部已經(jīng)給我們實(shí)現(xiàn)好了 肯定考慮到線程的問(wèn)題 以及其他的問(wèn)題 我們沒(méi)有想到的系統(tǒng)也給我們處理了。
    代碼實(shí)現(xiàn):
// 1.
static id _instance;

/**
 * 2.用GCD的dispatch_once方法重寫
 */
+ (id)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
         _instance = [super allocWithZone:zone];
    });
   return _instance;
}

// 3.
+ (instancetype)sharedMusicTool
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
         _instance = [[self alloc] init];
    });
    return _instance;
}

// 4.
- (id)copyWithZone:(NSZone *)zone
{
    return _instance;
}
  • 最后我們用一個(gè)宏的點(diǎn)h文件把所有的都包括了舵变,以后我們只需要把這個(gè)宏都帶進(jìn)去就可以了
// 在.h文件使用的宏定義
#define HJSingletonH(name) + (instancetype)shared##name;

#if __has_feature(objc_arc)
// 當(dāng)前的編譯器環(huán)境是ARC
// 在.m文件使用的宏定義
#define HJSingletonM(name) \
static id _instace; \
\
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [super allocWithZone:zone]; \
}); \
return _instace; \
} \
\
+ (instancetype)shared##name \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [[self alloc] init]; \
}); \
return _instace; \
} \
\
- (id)copyWithZone:(NSZone *)zone \
{ \
return _instace; \
}

#else
// 當(dāng)前的編譯器環(huán)境是MRC
// 在.m文件使用的宏定義
#define HJSingletonM(name) \
static id _instace; \
 \
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
        _instace = [super allocWithZone:zone]; \
    }); \
    return _instace; \
} \
 \
+ (instancetype)shared##name \
{ \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
        _instace = [[self alloc] init]; \
    }); \
    return _instace; \
} \
 \
- (id)copyWithZone:(NSZone *)zone \
{ \
    return _instace; \
} \
- (oneway void)release {} \
- (id)retain {return self;} \
- (NSUInteger)retainCount {return 1;} \
- (id)autorelease {return self;}
#endif

解釋:這個(gè)帶ARC和MRC的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末酣溃,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纪隙,更是在濱河造成了極大的恐慌赊豌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绵咱,死亡現(xiàn)場(chǎng)離奇詭異碘饼,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)悲伶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門艾恼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人拢切,你說(shuō)我怎么就攤上這事蒂萎。” “怎么了淮椰?”我有些...
    開(kāi)封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵五慈,是天一觀的道長(zhǎng)纳寂。 經(jīng)常有香客問(wèn)我,道長(zhǎng)泻拦,這世上最難降的妖魔是什么毙芜? 我笑而不...
    開(kāi)封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮争拐,結(jié)果婚禮上腋粥,老公的妹妹穿的比我還像新娘。我一直安慰自己架曹,他們只是感情好隘冲,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著绑雄,像睡著了一般展辞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上万牺,一...
    開(kāi)封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天罗珍,我揣著相機(jī)與錄音,去河邊找鬼脚粟。 笑死覆旱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的核无。 我是一名探鬼主播扣唱,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼团南!你這毒婦竟也來(lái)了画舌?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤已慢,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后霹购,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體佑惠,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年齐疙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了膜楷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贞奋,死狀恐怖赌厅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情轿塔,我是刑警寧澤特愿,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布仲墨,位于F島的核電站,受9級(jí)特大地震影響揍障,放射性物質(zhì)發(fā)生泄漏目养。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一毒嫡、第九天 我趴在偏房一處隱蔽的房頂上張望癌蚁。 院中可真熱鬧,春花似錦兜畸、人聲如沸努释。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)伐蒂。三九已至,卻和暖如春菲嘴,著一層夾襖步出監(jiān)牢的瞬間饿自,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工龄坪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昭雌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓健田,卻偏偏與公主長(zhǎng)得像烛卧,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子妓局,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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