單例模式是一種非常常見的設計模式,之前文章中UIApplication就是一種典型的單例模式,單例理解起來葉很簡單,就不是不管如果訪問始終只有一個實例化對象,定義全局共享的變量,如果對象是空則初始化一個對象,如果對象已經存在則使用已經實例化的對象。單例設計模式的作用是使得這個類的一個對象成為系統中的唯一實例,因此需要用一種唯一的方法去創建這個對象並返回這個對象的地址。下面有一張蘋果官網的圖片可以參考一下:
定義一個Food類,大家共享同一個食物,定義一個靜態變量,一個實例方法:
static Food *sharedFoodObj=nil;
+(Food *)sharedFood{
if (!sharedFoodObj) {
sharedFoodObj=[[Food alloc]init];
}
return sharedFoodObj;
}
執行以下代碼,最後發現兩個實例對象food和foodNext地址是一樣的:
Food *food=[Food sharedFood];
Food *foodNext=[Food sharedFood];
NSLog(@"共享地址:%p-共享地址:%p",food,foodNext);
如果每次都遵守規則調用sharedFood方法,單例模式算是完成了,但是對象是可以實例化的,看一段下面的代碼:
Food *food=[Food sharedFood];
Food *foodInit=[[Food alloc]init];
NSLog(@"共享地址:%p-實例地址:%p",food,foodInit);
food和foodInit的地址是不一樣,這個時候我們需要動手改造以下改成的方法,讓實例化對象的出來的地址也是一樣的,這個時候需要重寫allocWithZone方法:
+(Food *)sharedFood{
if (!sharedFoodObj) {
sharedFoodObj=[[super allocWithZone:NULL]init];
}
return sharedFoodObj;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
return [self sharedFood];
}
如果對象拷貝的時候也需要是同一對象的話,可以加一個方法:
+(id)copyWithZone:(struct _NSZone *)zone{
return [self sharedFood];
}
如果為了確保多線程情況下,仍然確保實體的唯一性,這個時候可以加上@synchronized,@synchronized的作用是創建一個互斥鎖,保證此時沒有其它線程對self對象進行修改。這個是objective-c的一個鎖定令牌,防止self對象在同一時間內被其它線程訪問,起到線程的保護作用。單例模式或者操作類的static變量中使用比較多。當兩個並發線程訪問同一個對象@synchronized(self)同步代碼塊時,一個時間內只能有一個線程得到執行。另一個線程必須等待當前線程執行完這個代碼塊以後才能執行該代碼塊。
+(Food *)sharedFood{
@synchronized(self){
if (!sharedFoodObj) {
sharedFoodObj=[[Food alloc]init];
}
}
return sharedFoodObj;
}
蘋果Mac OS 10.6和iOS4.0後引入了GCD,利用GCD(Grand Central Dispatch)和ARC(Automatic Reference Counting)實現單例,這個時候我們可以通過dispatch_once簡單的實現,代碼如下:
+ (instancetype)sharedInstance
{
static Food *sharedFoodObj = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedFoodObj =[[super allocWithZone:NULL]init];
});
return sharedFoodObj;
}
Food.m中的代碼:
//
// Food.m
// Demo
//http://www.cnblogs.com/xiaofeixiang
// Created by keso on 15/2/8.
// Copyright (c) 2015年 keso. All rights reserved.
//
#import "Food.h"
@implementation Food
static Food *sharedFoodObj=nil;
+(Food *)sharedFood{
if (!sharedFoodObj) {
sharedFoodObj=[[super allocWithZone:NULL]init];
}
return sharedFoodObj;
}
//
+(id)copyWithZone:(struct _NSZone *)zone{
return [self sharedFood];
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
+ (instancetype)sharedInstance
{
static Food *sharedFoodObj = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedFoodObj =[[super allocWithZone:NULL]init];
});
return sharedFoodObj;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
return [self sharedInstance];
}
@end
iOS的單例通過以上方式可以實現,網上有些文章實現單例用了七個方法,不過自從有了ARC之後,有些方法Apple已經不需要重寫,說一個題外話,昨天有個博客園的園友只字不改抄襲了我的文章,文章下面說明欄也說明過了(博客經個人辛苦努力所得,如有轉載會特別申明,博客不求技驚四座,但求與有緣人分享個人學習知識,生活學習提高之用),本人是自己辛苦所得,抄襲轉載麻煩留一個鏈接,技術文章技術人看,做一個技術人需要有些底線~