IOS 單例

轉載地址:http://blog.csdn.net/zhugq_1988/article/details/8568033


創建一個單例很多辦法。我先列舉一個蘋果官方文檔中的寫法。

 

[cpp] viewplaincopy
  1. static AccountManager *DefaultManager = nil;  
  2.    
  3. + (AccountManager *)defaultManager {  
  4.     if (!DefaultManager) DefaultManager = [[self allocWithZone:NULL] init];  
  5.     return DefaultManager;  
  6. }  

當然,在iOS4之後有了另外一種寫法:

 

 

[cpp] viewplaincopy
  1. + (AccountManager *)sharedManager  
  2. {  
  3.         static AccountManager *sharedAccountManagerInstance = nil;  
  4.         static dispatch_once_t predicate;  
  5.         dispatch_once(&predicate, ^{  
  6.                 sharedAccountManagerInstance = [[self alloc] init];   
  7.         });  
  8.     return sharedAccountManagerInstance;  
  9. }  

該寫法來自 objcolumnist,文中提到,該寫法具有以下幾個特性:

 

1. 線程安全。

2. 滿足靜態分析器的要求。

3. 兼容了ARC


然後我還有點好奇的是dispatch_once,這個函數,沒見過啊。

於是就到官方的文檔裏找找看,是怎麼說的。

下面是官方文檔介紹:

 

dispatch_once

Executes a block object once and only once for the lifetime of anapplication.

  void dispatch_once(

    dispatch_once_t*predicate,

    dispatch_block_t block);

Parameters

predicate

A pointer to a dispatch_once_t structure that is usedto test whether the block has completed or not.

block

The block object to execute once.

Discussion

This function is useful for initialization of global data(singletons) in an application. Always call this function beforeusing or testing any variables that are initialized by theblock.

If called simultaneously from multiple threads, this function waitssynchronously until the block has completed.

The predicate must point to a variable stored in global or staticscope. The result of using a predicate with automatic or dynamicstorage is undefined.

Availability

  • Available in iOS 4.0 and later.

Declared In

dispatch/once.h


我們看到,該方法的作用就是執行且在整個程序的聲明週期中,僅執行一次某一個block對象。簡直就是爲單例而生的嘛。而且,有些我們需要在程序開頭初始化的動作,如果爲了保證其,僅執行一次,也可以放到這個dispatch_once來執行。

然後我們看到它需要一個斷言來確定這個代碼塊是否執行,這個斷言的指針要保存起來,相對於第一種方法而言,還需要多保存一個指針。


方法簡介中就說的很清楚了:對於在應用中創建一個初始化一個全局的數據對象(單例模式),這個函數很有用。

如果同時在多線程中調用它,這個函數將等待同步等待,直至該block調用結束。

這個斷言的指針必須要全局化的保存,或者放在靜態區內。使用存放在自動分配區域或者動態區域的斷言,dispatch_once執行的結果是不可預知的。



總結:1.這個方法可以在創建單例或者某些初始化動作時使用,以保證其唯一性。2.該方法是線程安全的,所以請放心大膽的在子線程中使用。(前提是你的dispatch_once_t*predicate對象必須是全局或者靜態對象。這一點很重要,如果不能保證這一點,也就不能保證該方法只會被執行一次。)


單例模式作爲一種目標明確、結構簡單、理解容易的設計模式,在軟件開發中使用頻率相當高,在很多應用軟件和框架中都得以廣泛應用。

 

1.主要優點

      單例模式的主要優點如下:

      (1)單例模式提供了對唯一實例的受控訪問。因爲單例類封裝了它的唯一實例,所以它可以嚴格控制客戶怎樣以及何時訪問它。

      (2)由於在系統內存中只存在一個對象,因此可以節約系統資源,對於一些需要頻繁創建和銷燬的對象單例模式無疑可以提高系統的性能。

      (3)允許可變數目的實例。基於單例模式我們可以進行擴展,使用與單例控制相似的方法來獲得指定個數的對象實例,既節省系統資源,又解決了單例單例對象共享過多有損性能的問題。

 

2.主要缺點

      單例模式的主要缺點如下:

      (1) 由於單例模式中沒有抽象層,因此單例類的擴展有很大的困難。

      (2)單例類的職責過重,在一定程度上違背了“單一職責原則”。因爲單例類既充當了工廠角色,提供了工廠方法,同時又充當了產品角色,包含一些業務方法,將產品的創建和產品的本身的功能融合到一起。

      (3) 現在很多面嚮對象語言(JavaC#)的運行環境都提供了自動垃圾回收的技術,因此,如果實例化的共享對象長時間不被利用,系統會認爲它是垃圾,會自動銷燬並回收資源,下次利用時又將重新實例化,這將導致共享的單例對象狀態的丟失。

 

3.適用場景

      在以下情況下可以考慮使用單例模式:

      (1)系統只需要一個實例對象,如系統要求提供一個唯一的序列號生成器或資源管理器,或者需要考慮資源消耗太大而只允許創建一個對象。

      (2)客戶調用類的單個實例只允許使用一個公共訪問點,除了該公共訪問點,不能通過其他途徑訪問該實例。


發佈了8 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章