在讲单例之前先简单说明一个概念:“线程安全”。
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
在我们的程序中一定要注意线程安全的问题。
下面开始正题:
一、标准写法
这是一种很标准的Singleton实现,中规中矩。不过这种实现并不是线程安全的。
/* Singleton.h */
#import <Foundation/Foundation.h>
@interface Singleton : NSObject
+ (Singleton *)instance;
@end
/* Singleton.m */
#import "Singleton.h"
static Singleton *instance = nil;
@implementation Singleton
+ (Singleton *)instance {
if (!instance) {
instance = [[super allocWithZone:NULL] init];
}
return instance;
}
+ (id)allocWithZone:(NSZone *)zone {
return [self instance];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)init {
if (instance) {
return instance;
}
self = [super init];
return self;
}
- (id)retain {
return self;
}
- (oneway void)release {
// Do nothing
}
- (id)autorelease {
return self;
}
- (NSUInteger)retainCount {
return NSUIntegerMax;
}
@end
二、宏定义的单例模式
在这种模式下需要在程序中加入一个SynthesizeSingleton.h文件。在该文件中有使用的简单说明,很简单,就是在.h和.m文件中分别加入一句话即可,就可定义自己想要的单例。
Usage:
* MyClass.h:
* ========================================
* #import "SynthesizeSingleton.h"
*
* @interface MyClass: SomeSuperclass
* {
* ...
* }
* SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(MyClass);
*
* @end
* ========================================
*
*
* MyClass.m:
* ========================================
* #import "MyClass.h"
*
* // This line is optional. Use it if you've enabled GCC_WARN_UNDECLARED_SELECTOR
* SYNTHESIZE_SINGLETON_FOR_CLASS_PROTOTYPE(MyClass);
*
* @implementation MyClass
*
* SYNTHESIZE_SINGLETON_FOR_CLASS(MyClass);
*
* ...
*
* @end
* ========================================
三、比较现代的单例模式
为什么说现代呢?因为这种实现利用了GCD(Grand Central Dispatch)和ARC(Automatic Reference Counting)。核心代码如下:
+ (id)sharedPoiListViewController
{
static id poiListViewController;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
poiListViewController = [[self alloc] initWithStyle:UITableViewStylePlain];
});
return poiListViewController;
}
这段代码,在整个程序执行的过程中只会被调用一次,必定是县城安全的。