單例在我們開發中是最常用的設計模式,在iOS中也是如此。單例可以保證某個類的實例在程序中是唯一的,便於進行資源和數據的共享。使用的設計原則是單一職責原則。我們來看看在iOS中本身自帶的類或者方法哪些使用了單例的模式:
(1)UIAccelerometer類和sharedAccelerometer方法,一般如果方法名中有shared這樣的詞,就可以認為這是一個可以整個應用程序共享的實例變量,一般是使用了單例。
(2)UIApplication類和sharedApplication方法,我們一般使用該方法來創建全局變量。
(3)NSBundle類和mainBundle方法。
(4)NSFileManager類和defaultManager方法。
(5)NSNotificationCenter類和defaultManager方法。其中NSNotificationCenter也實現了觀察者模式。
(6)NSUserDefaults類和defaultUser方法。
今天我們嘗試自己來實現一個單例:
(1)新建一個普通的類,假設名字為Singleton. 在Singleton.h中聲明一個類方法,到時候使用該類方法(注意:一定是類方法,而不是實例方法)可以創建該類的唯一的一個實例:
#import@class Singleton; @interface Singleton : NSObject // "+" 表示類的方法,由類調用 +(Singleton *)sharedInstance; @end
#import "Singleton.h" // 用static聲明一個類的靜態實例; static Singleton *_sharedInstance = nil; @implementation Singleton /** * 1.使用類方法生成這個類唯一的實例; */ +(Singleton *)sharedInstance{ if (!_sharedInstance) { _sharedInstance =[[self alloc]init]; } return _sharedInstance; } @end
(3)我們使用一個簡單的demo來演示一下單例:
#import "RootVC.h" #import "Singleton.h" @interface RootVC () @end @implementation RootVC - (void)viewDidLoad { [super viewDidLoad]; [self testSigleTon]; } -(void)testSigleTon { //單例的結果就是,調用類方法,只返回一個共有的對象 /** * single和single2是同一個對象; 因為返回的數據是一個靜態變量,全局唯一; */ Singleton *single = [Singleton sharedInstance]; Singleton *single2 = [Singleton sharedInstance]; if (single == single2) { NSLog(@"single == single2"); } NSLog(@"single地址:%@",single); NSLog(@"single2地址:%@",single2); } @end
。
可以看到,兩個對象的內存地址是一樣的,表示這兩個對象其實是同一個對象,單例也就實現了。這是單例最普遍也是最簡單的實現方式,在項目中會經常用到,在不涉及多線程的情況下是完全正確的。但是,我們再多想一想,在多線程開發中,這種實現方式是否安全呢?那麼應該如何實現。我會在之後的博客中進行介紹。