iOS的单例模式(singleton)

      自从设计模式出现以后,关于单例模式的争执就一直存在。

我们非常多时候须要一个全局的东西,保证全局仅有一份就可以,这个时候单例是最佳的选择,但在多线程的环境下也须要做好线程保护。

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

      最简单的样例例如以下。如果我们有一个testClass的类须要实现单例:

+ (id)sharedInstance {
    static testClass *sharedInstance = nil;
    if (!sharedInstance) {
        sharedInstance = [[self alloc] init];
    }
    return sharedInstance;
}
      当然,你一眼就会发现。这里根本没有考虑线程安全的问题,让我们加上线程锁。

+ (id)sharedInstance {
    static testClass *sharedInstance = nil;
    @synchronized(self) {
        if (!sharedInstance) {
            sharedInstance = [[self alloc] init];
        }
    }
    return sharedInstance;
}
      这是非经常见的写法,假设继续下去,还须要重载retainCount,retain,等等方法。这个苹果的官方文档有论述到,甚至还有样例。

      只是,在GCD推出后,有个dispatch_once的方法,能够是单例的实现更加easy,dispatch_once的函数原型例如以下:

void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);

      我们能够看到这个函数接收一个dispatch_once_t的參数,另一个块參数。对于一个给定的predicate来说,该函数会保证相关的块必然会运行,并且仅仅运行一次,最重要的是——这种方法是全然线程安全的。须要注意的是。对于仅仅须要运行一次的块来说,传入的predicate必须是全然同样的,所以predicate经常会用static或者global来修饰。

+ (id)sharedInstance {
    static testClass *sharedInstance = nil;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });

    return sharedInstance;
}

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


posted @ 2017-08-19 19:02  jzdwajue  阅读(143)  评论(0编辑  收藏  举报