iOS的单例模式(singleton)

自从设计模式出现以后,关于单例模式的争执就一直存在。我们很多时候需要一个全局的东西,保证全局仅有一份即可,这个时候单例是最佳的选择,但在多线程的环境下也需要做好线程保护。

      在iOS下的UIApplication和NSFileManager就是很不错的例子——我们总有时候需要用到单例模式。不过写起代码来还是值得推敲一下:

      最简单的例子如下,假设我们有一个testClass的类需要实现单例:

  1. + (id)sharedInstance {  
  2.     static testClass *sharedInstance = nil;  
  3.     if (!sharedInstance) {  
  4.         sharedInstance = [[self alloc] init];  
  5.     }  
  6.     return sharedInstance;  
  7. }  
+ (id)sharedInstance {
    static testClass *sharedInstance = nil;
    if (!sharedInstance) {
        sharedInstance = [[self alloc] init];
    }
    return sharedInstance;
}

      当然,你一眼就会发现,这里根本没有考虑线程安全的问题,让我们加上线程锁。

 

  1. + (id)sharedInstance {  
  2.     static testClass *sharedInstance = nil;  
  3.     @synchronized(self) {  
  4.         if (!sharedInstance) {  
  5.             sharedInstance = [[self alloc] init];  
  6.         }  
  7.     }  
  8.     return sharedInstance;  
  9. }  
+ (id)sharedInstance {
    static testClass *sharedInstance = nil;
    @synchronized(self) {
        if (!sharedInstance) {
            sharedInstance = [[self alloc] init];
        }
    }
    return sharedInstance;
}

      这是很常见的写法,如果继续下去,还需要重载retainCount,retain,等等方法,这个苹果的官方文档有论述到,甚至还有例子。

 

      不过,在GCD推出后,有个dispatch_once的方法,可以是单例的实现更加容易,dispatch_once的函数原型如下:

  1. void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);  
void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);

 

      我们可以看到这个函数接收一个dispatch_once_t的参数,还有一个块参数。对于一个给定的predicate来说,该函数会保证相关的块必定会执行,而且只执行一次,最重要的是——这个方法是完全线程安全的。需要注意的是,对于只需要执行一次的块来说,传入的predicate必须是完全相同的,所以predicate常常会用static或者global来修饰。

  1. + (id)sharedInstance {  
  2.     static testClass *sharedInstance = nil;  
  3.     static dispatch_once_t once;  
  4.     dispatch_once(&once, ^{  
  5.         sharedInstance = [[self alloc] init];  
  6.     });  
  7.   
  8.     return sharedInstance;  
  9. }  
+ (id)sharedInstance {
    static testClass *sharedInstance = nil;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });

    return sharedInstance;
}

 

      这样写的好处很明显:代码简单清晰,而且做到了线程安全。另外,dispatch_once很高效,没有实现重量级的同步机制,这样实现的效率也很高。

http://blog.csdn.net/sakulafly/article/details/34948689

posted @ 2014-07-13 00:05  codeTao  阅读(150)  评论(0编辑  收藏  举报