如何使用單例模式

可以看下這個圖:

這是一個日誌類,有一個屬性 (是一個單例對象) 和兩個方法 (sharedInstance()init())。

第一次調用 sharedInstance() 的時候,instance 屬性還沒有初始化。所以我們要創建一個新實例並且返回。

下一次你再調用 sharedInstance() 的時候,instance 已經初始化完成,直接返回即可。這個邏輯確保了這個類別只存在一個實體對象。

依據這個邏輯,我們也可以寫一個單例模式,通過這個類別來管理圖片數據資料。

我們可以新建一個檔案ImageCache.swift,並添加下面這些程式碼。

先建立一個名為ImageCache的類別,再宣告一個名稱為mInstance的靜態變數,並且型別為ImageCache自己本身,為可選值,而且雖然是靜態變數,可是存取權限要設定為private私有的,除了自己以外,其他類別成員都不能夠去操作存取這個靜態變數。

單例設計模式的奧妙,就在於下一步要做的,我們再宣告一個靜態方法sharedInstance(),回傳值型別也是ImageCache,並且我們要在裡面加入單例設計模式的主要邏輯。

如果其他類別成員要透過sharedInstance()這個方法取得ImageCache的實體時,就會開始判斷mInstance是否為空值:

  • 如果不是空值,就直接回傳mInstance

  • 如果是空值,就初始化一個實體。

單一設計模式下,封裝了兩個邏輯,一個是私有的靜態變數,一個是公開的靜態方法。

私有的靜態變數mInstance,通過 static定義意味著這個屬性只存在一個。公開的靜態方法sharedInstance,直到需要的時候才會被初始化。

同時再注意一下,因為它是一個唯讀的常數,所以一旦建立之後,不會也不能夠再建立第二次,也不能夠被別的值所取代。

這些就是單例模式的核心所在:一旦初始化完成,當前類別存在一個實例物件,初始化方法就不會再被調用。

最後,我們再複寫掉初始化方法,把建構式私有化,讓他不能被其他類別成員用除了靜態方法sharedInstance以外的方式實體化,以確保單例模式的唯一性。

我們現在可以將這個單例作為圖片資料快取儲存,接下來我們繼續完成他全部的功能。

在這裡我們定義了一個私有屬性,用來存儲照片資料。這是一個字典變數,所以值為字串,在單例模式下,ImageCache類別只會存在一份實體,同樣的在這類別裡面的mImages:[String:UIImage]字典裡面,也只會存在一個實體。

我們會把圖片儲存到手機本機端,這樣可以避免一次又一次下載相同的照片。

程式內容很簡單直接,下載的照片會儲存在 Documents 目錄下,如果沒有檢查到暫存檔案, getImage() 方法則會返回 nil 。

我們開始運用看看: 打開PhotoView.swift這個類別,

下載完圖片以後,直接儲存到圖片快取裡面。

我們使用外觀模式隱藏了下載圖片的複雜程度。通知的發送者並不在乎圖片是如何從網上下載到本地的。

我們先開始做最開始的版型排版:

先打開MainViewController.swift,開始編輯裡面的viewDidLoad,並且加ㄧ個變數用來儲存會顯示的全部的PhotoView,在宣告一個變數用來建立 FlickrModel 的實體。

然後,我們在寫上測試到目前功能的程式碼:

然後,我們在viewDidload執行我們剛剛所寫的程式碼:

而原本測試的 PhotoDelegate就先刪除吧,避免程式碼的雜亂。

在模擬器中執行,會發現一開始會出現10個整齊排列的藍色框框,這些都是我們寫的 PhotoView,如果網路正常的情況下,會在Xcode 裡的 Console 視窗出現LoadFlickrDataComplete!count:99,表示 Flickr 的資料載入完成,然後我們再按下最下面的紅色按鈕,載入圖片。

完成到這一步的Demo:

Last updated

Was this helpful?