概述
單例在不同的語言當中可能定義可能不一定完全相同,但宗旨應(yīng)該是一樣的:該類在程序運行期間有且僅有一個實例
所以,在使用單例的時候要考慮好自己的需求是否真的需要,過度使用是不好的
1.單例的優(yōu)點(主要優(yōu)點)
單例可以保證系統(tǒng)中該類有且僅有一個實例,所以很便于外界訪問.
因為其上面的特點,對于項目中的個別場景的傳值,存儲狀態(tài)等等更加方便
2.單例的缺點(主要缺點)
單例實例一旦創(chuàng)建,對象指針是保存在靜態(tài)區(qū)的,那么在堆區(qū)分配空間只有在應(yīng)用程序終止后才會被釋放
單例不能繼承
單例的實現(xiàn)(所有的代碼實現(xiàn)都是基于ARC模式下)
單例的實現(xiàn)重點就是防止在外部調(diào)用的時候出現(xiàn)多個不同的實例,也就是說我們要從創(chuàng)建的方式入手禁止出現(xiàn)多個不同的實例
相信大家都知道經(jīng)常出現(xiàn)錯誤的就是在不知情的情況下掉用的系統(tǒng)的一些初始化方法, 如果是自己手誤那就知道怎么說你了哈哈,如果其他人使用你創(chuàng)建的類不看對外接口 那這個隊友還是需要有待提高的(前提是你要寫的清楚寫注釋)
個人觀點主要是做到以下幾點:
防止調(diào)用 alloc]init]引起的錯誤
防止調(diào)用 new 引起的錯誤
防止調(diào)用 copy 引起的錯誤(應(yīng)該不常用)
防止調(diào)用 mutableCopy 引起的錯誤(應(yīng)該不常用)
實現(xiàn)方法一
首先需要使用GCD來實現(xiàn)的單例創(chuàng)建,為啥使用GCD請自行學(xué)習
第一步 (必不可少的)
- (instancetype)sharedSingleton {
static Singleton *_sharedSingleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//不能再使用alloc方法
//因為已經(jīng)重寫了allocWithZone方法式镐,所以這里要調(diào)用父類的分配空間的方法
_sharedSingleton = [[super allocWithZone:NULL] init];
});
return _sharedSingleton;
}
第二步
防止alloc] init] 和new引起的錯誤,因為alloc] init] 和 new 實際是一樣的工作原理.都是執(zhí)行了下面方法
// 防止外部調(diào)用alloc 或者 new - (instancetype)allocWithZone:(struct _NSZone *)zone {
return [Singleton sharedSingleton];
}
第三步 NSCopying
防止copy引起的錯誤,個人感覺當你的單例類不遵循NSCopying協(xié)議,外部調(diào)用本身就會出錯. 如果不是業(yè)務(wù)需求不遵循協(xié)議,該方法也可以不寫 這都是個人觀點 不過為了嚴謹還是寫吧
// 防止外部調(diào)用copy
- (id)copyWithZone:(nullable NSZone *)zone {
return [Singleton sharedSingleton];
}
第四步
防止mutableCopy引起的錯誤,個人感覺當你的單例類不遵循NSMutableCopying協(xié)議,外部調(diào)用本身就會出錯. 如果不是業(yè)務(wù)需求不遵循協(xié)議,該方法也可以不寫 這都是個人觀點 不過為了嚴謹還是寫吧
// 防止外部調(diào)用mutableCopy - (id)mutableCopyWithZone:(nullable NSZone *)zone {
return [Singleton sharedSingleton];
}
實現(xiàn)方法二
上面的方法是把其可能出現(xiàn)的初始化方法做了相應(yīng)的處理來其保證安全性
其實我們可以在不做處理的情況下 禁止外部調(diào)用豈不是更簡單 個人感覺該方法也很不錯而且一些成熟的第三方中的單例中也有使用該方法的
直接在你創(chuàng)建的單例文件的.h文件中加入代碼
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)new NS_UNAVAILABLE;
- (id)copy NS_UNAVAILABLE; // 沒有遵循協(xié)議可以不寫
- (id)mutableCopy NS_UNAVAILABLE; // 沒有遵循協(xié)議可以不寫
.m文件實現(xiàn)一個方法即可,上面方式的其他方法就不要寫了
// 跟上面的方法實現(xiàn)有一點不同
- (instancetype)sharedSingleton {
static Singleton *_sharedSingleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 要使用self來調(diào)用
_sharedSingleton = [[self alloc] init];
});
return _sharedSingleton;
}
以上的運行結(jié)果可以自行測試
其實單例的寫法的重點以及理解 都是考察對內(nèi)存的分配的認識. (本人能力有限還需學(xué)習)
以上的都是個人總結(jié),也許有不對或者不妥當?shù)牡胤?也希望大家指正