- 版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。
單例模式的意思就是只有一個實例。單例模式確保某一個類只有一個實例,而且自行實例化并向整個系統(tǒng)提供這個實例。這個類稱為單例類。
1.單例模式的要點:
顯然單例模式的要點有三個;一是某個類只能有一個實例;二是它必須自行創(chuàng)建這個實例;三是它必須自行向整個系統(tǒng)提供這個實例。
2.單例模式的優(yōu)點:
1.實例控制:Singleton 會阻止其他對象實例化其自己的 Singleton 對象的副本,從而確保所有對象都訪問唯一實例。
2.靈活性:因為類控制了實例化過程,所以類可以更加靈活修改實例化過程
iOS中的單例模式
- 在objective-c中要實現(xiàn)一個單例類,至少需要做以下四個步驟:
1、為單例對象實現(xiàn)一個靜態(tài)實例,并初始化,然后設(shè)置成nil,
2、實現(xiàn)一個實例構(gòu)造方法檢查上面聲明的靜態(tài)實例是否為nil,如果是則新建并返回一個本類的實例,
3、重寫allocWithZone方法,用來保證其他人直接使用alloc和init試圖獲得一個新實力的時候不產(chǎn)生一個新實例,
4、適當(dāng)實現(xiàn)allocWitheZone,copyWithZone,release和autorelease。
- 下面以SurveyRunTimeData為例子:
static MyClass *class = nil;
@implementation MyClass
+(MyClass *)sharedMyClass{
@synchronized(self){ //為了確保多線程情況下,仍然確保實體的唯一性
if (!class) {
[[self alloc] init]; //該方法會調(diào)用 allocWithZone
}
}
return class;
}
+(id)allocWithZone:(NSZone *)zone{
@synchronized(self){// //為了確保多線程情況下,仍然確保實體的唯一性
if (!class) {
class = [super allocWithZone:zone]; //確保使用同一塊內(nèi)存地址
return class;
}
}
return nil;
}
-(id)init
{
if(class){
return class;
}
if(self = [super init]){
//進(jìn)行一些初始化
}
return self ;
}
- (id)copyWithZone:(NSZone *)zone;{
return self; //確保copy對象也是唯一
}
-(id)retain{
return self; //確保計數(shù)唯一
}
- (unsigned)retainCount
{
return UINT_MAX; //裝逼用的,這樣打印出來的計數(shù)永遠(yuǎn)為-1
}
- (id)autorelease
{
return self;//確保計數(shù)唯一
}
- (oneway void)release
{
//重寫計數(shù)釋放方法 do nothing
}
@end ```
>再調(diào)試
MyClass *A = [[MyClass alloc] init];
NSLog(@"A:%@",A);
MyClass *B = [MyClass sharedMyClass];
NSLog(@"B:%@",B);
MyClass *C = [A copy];
NSLog(@"C:%@",C);```
打印出的是
A:<MyClass: 0x6a1e130>
B:<MyClass: 0x6a1e130>
C:<MyClass: 0x6a1e130>```
>都是指向同一塊內(nèi)存地址
- 然而這個人(<http://eschatologist.net/blog/?p=178>)覺的繁瑣,所以給出如下實現(xiàn):
@interface SomeManager : NSObject
- (id)sharedManager;
@end
/* 非線程安全的實現(xiàn) */
@implementation SomeManager
-
(id)sharedManager {
static id sharedManager = nil;if (sharedManager == nil) {
sharedManager = [[self alloc] init];
}return sharedManager;
}
@end
/* 線程安全的實現(xiàn) */
@implementation SomeManager
static id sharedManager = nil;
(void)initialize {
if (self == [SomeManager class]) {
sharedManager = [[self alloc] init];
}
}(id)sharedManager {
return sharedManager;
}
@end ```
自蘋果引入了
Grand Central Dispatch (GCD)(Mac OS 10.6和iOS4.0)后,利用GCD(Grand Central Dispatch)和ARC(Automatic Reference Counting)實現(xiàn)單例。
+(SchoolManager *)sharedInstance
{
__strong static SchoolManager *sharedManager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [[SchoolManager alloc] init];
});
return sharedManager;
} ```
>函數(shù)void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);其中第一個參數(shù)predicate,該參數(shù)是檢查后面第二個參數(shù)所代表的代碼塊是否被調(diào)用的謂詞,第二個參數(shù)則是在整個應(yīng)用程序中只會被調(diào)用一次的代碼塊。dispach_once函數(shù)中的代碼塊只會被執(zhí)行一次,而且還是線程安全的。
看到如下一篇文章,用宏實現(xiàn)(<https://gist.github.com/lukeredpath/1057420>):
//ExampleClass.m
@implementation MySharedThing
- (id)sharedInstance
{
DEFINE_SHARED_INSTANCE_USING_BLOCK(^{
return [[self alloc] init];
});
}
@end
GCDSingleton.h
define DEFINE_SHARED_INSTANCE_USING_BLOCK(block)
static dispatch_once_t pred = 0;
__strong static id _sharedObject = nil;
dispatch_once(&pred, ^{
_sharedObject = block();
});
return _sharedObject;