OC中兩種單例實現方式


OC中兩種單例實現方式

寫在前面
前兩天探索了一下C++ 的單例,領悟深刻了許多。今天來看看OC中的單例又是怎么回事。查看相關資料,發現在OC中一般有兩種實現單例的方式,一種方式是跟C++ 中類似的常規實現方法,另一種是利用GCD來實現的。接下來分別看看這兩種單例實現方式是怎么做的

常規實現

與C++中的相似,在OC中實現單例需要滿足以下條件:

  1. 設計一個私有的構造方法

  2. 設計一個私有的,本類的對象

  3. 設計一個類方法,作為2中類對象的全局訪問點
    接下來我們逐個解決上述3個條件。
    首先,將構造函數設計為私有的。在OC中,對象的創建包括兩個步驟:內存申請(alloc)和初始化(init)。也就是說,如果我們希望構造函數私有,那么我們要自己定義alloc方法,使得每次調用該方法,都返回條件2中的對象。在OC中,調用alloc時,alloc實際上是調用allocWithZone這個方法來申請內存的,因此,我們在設計單例的時候,要重寫這個方法。另外,我們還要保證使用copy復制單例中的對象時,返回的也是步驟2中的對象,而不會重新創建,因此,我們還要重寫copyWithZone這個方法。具體代碼如下
    .h文件:

// // Singleton.h // Singleton // #import <Foundation/Foundation.h> @interface Singleton : NSObject //類方法 + (Singleton *) getInstance; @end 

.m文件

// // Singleton.m // Singleton // #import "Singleton.h" @implementation Singleton //在.m文件中聲明靜態的類實例,不放在.h中是為了讓instance私有 static Singleton* instance = nil; //提供的類唯一實例的全局訪問點 //跟C++中思路相似,判斷instance是否為空 //如果為空,則創建,如果不是,則返回已經存在的instance //不能保證線程安全 +(Singleton *) getInstance{ if (instance == nil) { instance = [[Singleton alloc] init];//調用自己改寫的”私有構造函數“ } return instance; } //相當於將構造函數設置為私有,類的實例只能初始化一次 +(id) allocWithZone:(struct _NSZone*)zone { if (instance == nil) { instance = [super allocWithZone:zone]; } return instance; } //重寫copy方法中會調用的copyWithZone方法,確保單例實例復制時不會重新創建 -(id) copyWithZone:(struct _NSZone *)zone { return instance; } @end 

main函數文件

// main.m // Singleton // #import <Foundation/Foundation.h> #import "Singleton.h" int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... //用getInstance方法創建實例1、2並打印內容 Singleton *singleton1 = [Singleton getInstance]; NSLog(@"singleton1 = %@.", singleton1); Singleton *singleton2 = [Singleton getInstance]; NSLog(@"singleton2 = %@.", singleton2); //用alloc+init創建實例3並打印內容 Singleton *singleton3 = [[Singleton alloc] init]; NSLog(@"singleton3 = %@.", singleton3);
//用alloc+init創建實例4,打印copy后的內容 Singleton *singleton4 = [[Singleton alloc] init]; NSLog(@"singleton4 = %@.", [singleton4 copy]); } return 0; } /

結果
enter description here

可以看到,所有的是咧地址都是相同的,也就是或,返回的是同一個地址

GCD方式的單例

GCD是蘋果提供的一種多線程的實現方案。使用GCD,用戶不用手動管理線程的生命周期,非常方便。GCD提供了一個多線程下,一段代碼只被執行一次的方式:dispath_once。這種方式是線程安全的。代碼如下,(其余代碼與常規方式相同,不再復制)

//使用gcd中的dispatch_once()方法,函數的第二個參數是一個代碼段,告訴gcd我們要做的事情是什么 +(Singleton *) getInstance{  static dispatch_once_t onceToken;  dispatch_once(&onceToken, ^{  instance = [[self alloc]init]; });  return instance; } //使用gcd的dispatch_once()方法,在傳入的代碼段中,調用父類的內存申請函數 +(id) allocWithZone:(struct _NSZone*)zone {  static dispatch_once_t onceToken;  dispatch_once(&onceToken, ^{  instance = [super allocWithZone:zone]; });  return instance; } 

結果如下:
enter description here

這個結果也證明了,最后創建的類的實例只有一個


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM