Objective-C Singleton Pattern

根据该文章写了一篇关于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;
  }
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值