根据该文章写了一篇关于iOS单例模式的文章:http://duckrowing.com/2010/05/21/using-the-singleton-pattern-in-objective-c/
单例模式是在软件设计中很常用的一个模式,所谓单例,就是只能有一个实例化对象的类.
在iOS中,常见的单例:
// Some singletons in the CocoaTouch libraries
UIApplication *applicationSingleton = [UIApplication sharedApplication];
UIAccelerometer *accelerometerSingleton = [UIAccelerometer sharedAccelerometer];
显而易见,在iOS中,一个App中只能有一个App的代理类的实例,那就正在的这个程序本身,同样,一台设备也只有一个加速计.
熟悉iOS编程的都应该熟悉,在iOS中获取单例对象的方法,一般都以shared开头的.
不同于原作者提到的Ruby和Scala,Objective-C本身并没有提供原生的单例模式,所以在Objective-C中,如果我们需要使用单例模式,那么,我们就得自己去实现,并且确保在程序运行时,有且只有一个实例.
从这里开始引用原作者的代码:
/**
This class simulates access to a hardware radio tuner. In our example
we assume that our computer has a single radio tuner that must be shared.
*/
@interface RadioTuner : NSObject {
NSDecimalNumber *currentStation;
}
/**
Returns an instance to the shared singleton which governs access to the
hardware radio tuner.
@returns The shared tuner object
*/
+ (RadioTuner *)sharedTuner;
/**
Sets the tuner to the desired station
@param station the new station frequency
*/
- (void)setStation:(NSDecimalNumber *)station;
/**
Get the current station
@returns returns the current statiion to which the tuner is tuned.
*/
- (NSDecimalNumber *)currentStation;
@end
作者在此创建了一个RadioTuner类,其中有三个方法,工厂方法sharedTuner显然是用来获取单例的方法,命名也符合objc中的习惯.还有两个用来get,set
RadioTuner当前状态的对象方法.头文件是极其简单,下面看看这些方法的实现.
对于[RadioTuner sharedTuner]这个方法,我们得保证每次调用返回的都是同一个对象,并且也是获取这个单例对象的唯一方法.
在开始之前,我们得有一个指针,指向生成的单例对象,让我们能随时获取它.
#import "RadioTuner.h"
static RadioTuner *sharedInstance = nil;
@implementation RadioTuner
这只不过是C语言基础的静态变量声明.静态变量的生命周期覆盖整个程序运行.
现在,我们来写sharedTuner方法的实现:
+ (RadioTuner *)sharedTuner
{
@synchronized (self) {
if (sharedInstance == nil) {
[[self alloc] init];
}
}
return sharedInstance;
}
这里有2个事情需要注意,第一,这个方法是同步化的.防止被同时调用.作者在这里扯了一堆觉得不用如此的话,但最终,他还是写成了同步化,所以,我们就老老实实这样写吧.
第二个就是这个方法并给sharedInstance赋值,这看起来很违反常识,但下面这个方法的实现,为我们解释了为何要我们这么做.
+ (id)allocWithZone:(NSZone *)zone
{
@synchronized(self) {
if (sharedInstance == nil) {
sharedInstance = [super allocWithZone:zone];
return sharedInstance;
}
}
return nil;
}
注:原作者在这里说是为了优化内存,并且还有链接,我觉得对我而言太复杂,有兴趣的各位自己研究吧.
这里,我们只关心----只有当sharedInstance为nil时,才会分配内存,这样就只有第一次调用[RadioTuner alloc]的时候才会为之分配内存,其后的调用都不会有作用,这样就保证无论何时,几次调用[RadioTuner sharedTuner]都只会返回同一个对象的引用.
另外,为了保证copy,ratain,autorelease的正常运行,我们同样需要覆盖一下几个方法.
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain
{
return self;
}
- (void)release
{
// do nothing
}
- (id)autorelease
{
return self;
}
- (NSUInteger)retainCount
{
return NSUIntegerMax; // This is sooo not zero
}
这个单例模板的最后3个方法:
- (id)init
{
@synchronized(self) {
[super init];
currentStation = [[NSDecimalNumber alloc] initWithString:@"0.0"];
return self;
}
}
- (void)setStation:(NSDecimalNumber *)station
{
@synchronized(self) {
if (currentStation != station) {
[currentStation release];
currentStation = [station retain];
}
}
}
- (NSDecimalNumber *)currentStation
{
@synchronized(self) {
return currentStation;
}
}