iOS開發-單例模式的解讀,ios開發解讀

來源:互聯網
上載者:User

iOS開發-單例模式的解讀,ios開發解讀

現在網上的有很多人寫單例模式,一個很基本的東西但是版本也有很多,新人看了難免有些眼花繚亂的感覺。自己最新比較閑,也過來寫一些自己的心得。

在往下看之前,我們要明白一點,那就是在什麼情況下我們才要用到單例模式呢?單例模式在一般情況下用於當一個類只能有一個執行個體的時候,或者說當一個類只需要定義一個,而且還要被重複使用的時候將它定義成為單例是最好的。(例如視頻播放器,音頻播放器等工具類用用單例模式加以控制是非常合適的)

在建立一個單例之前,我們還需要知道一點,那就是我們建立一個單例,我們的最終目的是什麼呢?

單例模式需要達到的目的:

1. 封裝一個共用的資源

2. 提供一個固定的執行個體建立方法

3. 提供一個標準的執行個體提供者

 

好了,接下來我們就要開始了,為了規範我們應該需要知道建立一個單例具體是有哪幾個步驟呢?

在iOS中我們建立一個單例類,我們需要做3個步驟

1、先為我們要做的單例建立一個靜態執行個體,並初始化它,然後設定成為nil;

2、在下面的執行個體構造方法中檢查在第1步中聲明的靜態執行個體是否為nil,若判斷為真,那麼就建立一個並且返回一個本例的執行個體;

3、重載所有涉及到allocation的方法,對allocWithZone,copyWithZone,release以及autorelease進行重載,這樣的話即使在別的地方使用alloc和init方法建立該類的話也不會再產生一個新的執行個體了;

 

單例模式的建立

假設以建立一個PlayViewController的單例模式為例:

1、首先建立一個靜態執行個體

1 static PlayViewController *PlayManager = nil;  

 

2、然後為其添加一個類方法

1 static PlayViewController *PlayManager = nil;  

2+ ( PlayViewController *)defaultManager{  

3     @synchronized(self) {  

4         if(PlayManager == nil) {  

5             [[[self class] alloc] init]; 

6         }  

7     }  

8     return PlayManager;  

9 }  

回顧總結:

a、用到了關鍵字@synchronized是為了保證我們的單例的線程層級的安全,可以適用於多線程模式下。

b、static變數PlayManager用於儲存一個單例的指標,並且強制所有對該變數的訪問都必須通過類方法 +(id)defaultManager,在對 +(id)defaultManager第一次調用時候完成執行個體的建立。

c、上面代碼中用的是[[self   class] alloc],而不是 [PlayViewController alloc],一般情況下這兩種寫法產生同樣的效果,但是這裡這樣做是為了更好的利用OOP的性質,[self class]可以動態尋找並確定類的類型從而便於實現對該類的子類化。

 

3、這個時候建立的單例並不能說是真正意義上的單例,因為他還不具備單例的單態性,所以我們還要通過一些方法來避免單例被多次重複建立。也就是說當使用者不使用+(id)defaultManager建立對象,而是使用alloc方法建立對象時,就會又產生一個對象執行個體,這跟我們最初只想建立一個單例的想法相衝突,那麼我們怎麼辦呢?

我們可以看到,在方法+(PlayViewController *)defaultManager中只是解決了單例的建立和訪問,但是並不能限制其他地方的代碼通過alloc方法來建立更多的執行個體,所以,所有涉及到allocation的方法我們都需要進行重載,這些方法包括+(id)alloc、+(id)allocWithZone、-(id)copyWithZone。

1 + (id)alloc  

2 {  

3     @synchronized(self) {  

4         if(PlayManager == nil) {  

5             PlayManager = [super alloc];  

6         }  

7   return PlayManager;  

8        } 

9 }  

 

1 +(id)allocWithZone:(NSZone*)zone

2 {  

3     @synchronized(self) {  

4         if(PlayManager == nil) {  

5             PlayManager = [super allocWithZone:zone]; 

6             }

7                return  PlayManager;

8         } 

9 }  

 

1 -   (id)copyWithZone:(NSZone *)zone  

2 {      

3     return self;  

4 }  

回顧總結:

很多時候,我們會發現在有的單例裡面對於alloc方法,並沒有進行重載,而只是單純的重載了allocWithZone方法。這是為什麼呢?

因為重載allocWithZone是一個比較全面的方法,在使用alloc方法時,alloc方法自身會調用allocWithZone這個方法。而使用allocWithZone時則不會調用alloc方法。

所以很多時候沒必要重寫alloc,直接重寫allocWithZone即可。(也就是說只要定義一個allocWithZone就可以了)

 

 上述的代碼只是在ARC中可以正確使用,如果實在MRC中,有retain,copy,release, autorelease,這些方法都會使得引用計數變化,所以,我們都需要對這些方法重寫。

1 -   (id)retain

2 {    

3     return self;  

4 

 

1 -   (id)copy

2 {    

3     return self;  

4 }  

 

 

1- (oneway void) release

2{

3

4}

 

1- (id) autorelease

2{

3    return self;

4}

 

1- (NSUInteger) retainCount

2{

3    return 1;

4}

 

1- (id)init

2{

3    @synchronized(self) {

4        [super init];//往往放一些要初始化的變數.

5        return self;

6    }

7 }

好了,到這裡為止,一個單例的建立算是正式結束了。

謝謝大家的閱讀,如果發現有什麼不妥當的地方,還請大家留言指出問題!!!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.