單例模式

 

 

單例模式

  • 1.1 概念相關

(1)單例模式程序員

在程序運行過程,一個類只有一個實例

(2)使用場合web

在整個應用程序中,共享一份資源(這份資源只須要建立初始化1次)
  • 1.2 ARC實現單例

(1)步驟網絡

01 在類的內部提供一個static修飾的全局變量
02 提供一個類方法,方便外界訪問
03 重寫+allocWithZone方法,保證永遠都只爲單例對象分配一次內存空間
04 嚴謹起見,重寫-copyWithZone方法和-MutableCopyWithZone方法

(2)相關代碼ide

//提供一個static修飾的全局變量,強引用着已經實例化的單例對象實例
static ZYQTools *_instance;

//類方法,返回一個單例對象
+(instancetype)shareTools
{
     //注意:這裏建議使用self,而不是直接使用類名Tools(考慮繼承)
    return [[self alloc]init];
}

//保證永遠只分配一次存儲空間
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
    //使用GCD中的一次性代碼
//    static dispatch_once_t onceToken;
//    dispatch_once(&onceToken, ^{
//        _instance = [super allocWithZone:zone];
//    });

    //使用加鎖的方式,保證只分配一次存儲空間
    @synchronized(self) {
        if (_instance == nil) {
// 調用系統的allocWithZone方法 _instance = [super allocWithZone:zone]; } } return _instance; } /* 1. mutableCopy 建立一個新的可變對象,並初始化爲原對象的值,新對象的引用計數爲 1; 2. copy 返回一個不可變對象。分兩種狀況:
(1)若原對象是不可變對象,那麼返回原對象,並將其引用計數加 1 ;
(2)若原對象是可變對象,那麼建立一個新的不可變對象,並初始化爲原對象的值,新對象的引用計數爲 1。 */ //讓代碼更加的嚴謹 -(nonnull id)copyWithZone:(nullable NSZone *)zone { // return [[self class] allocWithZone:zone]; return _instance; } -(nonnull id)mutableCopyWithZone:(nullable NSZone *)zone { return _instance; }llocWithZone
  • 1.3 MRC實現單例

(1)實現步驟ui

01 在類的內部提供一個static修飾的全局變量
02 提供一個類方法,方便外界訪問
03 重寫+allocWithZone方法,保證永遠都只爲單例對象分配一次內存空間
04 嚴謹起見,重寫-copyWithZone方法和-MutableCopyWithZone方法
05 重寫release方法
06 重寫retain方法
07 建議在retainCount方法中返回一個最大值

(2)配置MRC環境知識url

01 注意ARC不是垃圾回收機制,是編譯器特性
02 配置MRC環境:build setting ->搜索automatic ref->修改成NO

(3)相關代碼spa

//提供一個static修飾的全局變量,強引用着已經實例化的單例對象實例
static ZYQTools *_instance;

//類方法,返回一個單例對象
+(instancetype)shareTools
{
     //注意:這裏建議使用self,而不是直接使用類名Tools(考慮繼承)

    return [[self alloc]init];
}

//保證永遠只分配一次存儲空間
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
    //使用GCD中的一次性代碼
//    static dispatch_once_t onceToken;
//    dispatch_once(&onceToken, ^{
//        _instance = [super allocWithZone:zone];
//    });

    //使用加鎖的方式,保證只分配一次存儲空間
    @synchronized(self) {
        if (_instance == nil) {
            _instance = [super allocWithZone:zone];
        }
    }
    return _instance;
}

//讓代碼更加的嚴謹
-(nonnull id)copyWithZone:(nullable NSZone *)zone
{
//    return [[self class] allocWithZone:zone];
    return _instance;
}

-(nonnull id)mutableCopyWithZone:(nullable NSZone *)zone
{
    return _instance;
}

//在MRC環境下,若是用戶retain了一次,那麼直接返回instance變量,不對引用計數器+1
//若是用戶release了一次,那麼什麼都不作,由於單例模式在整個程序運行過程當中都擁有且只有一份,程序退出以後被釋放,因此不須要對引用計數器操做
-(oneway void)release
{
}

-(instancetype)retain
{
    return _instance;
}

//習慣用法,有經驗的程序員經過打印retainCount這個值能夠猜到這是一個單例
-(NSUInteger)retainCount
{
    return MAXFLOAT;
}
  • 1.4 通用版本

(1)問答區3d

01 問:寫一份單例代碼在ARC和MRC環境下都適用?
答:可使用條件編譯來判斷當前項目環境是ARC仍是MRC(建立一個.h文件)
02 問:條件編譯的代碼呢?
//答:條件編譯
#if __has_feature(objc_arc)
//若是是ARC,那麼就執行這裏的代碼1
#else
//若是不是ARC,那麼就執行代理的代碼2
#endif
03 問:在項目裏面每每須要實現不少的單例,好比下載、網絡請求、音樂播放等等,弱弱的問一句單例能夠用繼承嗎?
答:單例是不能夠用繼承的,若是想一次寫,就能四處使用,那麼推薦親使用帶參數的宏定義啦!

04 問:宏定義怎麼弄?
答:look!


(2)使用帶參數的宏完成通用版單例模式代碼代理

01 注意條件編譯的代碼不能包含在宏定義裏面
02 宏定義的代碼只須要寫一次就好,以後直接拖到項目中用就OK
相關文章
相關標籤/搜索