单例模式算是开发中比较常见的一种模式了。在iOS中,单例有两种实现方式(至少我目前只发现两种)。根据线程安全的实现来区分,一种是使用@synchronized,另一种是使用GCD的dispatch_once函数。

要实现单例,首先需要一个static的指向类本身的对象,其次需要一个初始化类函数。下面是两种实现的代码。

1、@synchronized

static InstanceClass *instance;
+ (InstanceClass *)defaultInstance{
@synchronized (self){
if (instance == nil) {
instance = [[InstanceClass alloc] init];
}
} return instance;
}

2、GCD

static InstanceClass *instance;
+ (InstanceClass *)defaultInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[InstanceClass alloc] init];
}); return instance;
}

总的来说,两种实现效果相同,但第二种GCD的实现方式写起来比较简单。如果不习惯GCD的方式,可以使用第一种方式。

两种单利模式的优劣:

单次初始化

GCD还提供单词初始化支持,这个与pthread中的函数  pthread_once 很相似。GCD提供的方式的优点在于它使用block而非函数指针,这就允许更自然的代码方式:

这个特性的主要用途是惰性单例初始化或者其他的线程安全数据共享。典型的单例初始化技术看起来像这样(线程安全的):

    + (id)sharedWhatever
{
static Whatever *whatever = nil;
@synchronized([Whatever class])
{
if(!whatever)
whatever = [[Whatever alloc] init];
}
return whatever;
}

这挺好的,但是代价比较昂贵;每次调用  +sharedWhatever 函数都会付出取锁的代价,即使这个锁只需要进行一次。确实有更风骚的方式来实现这个,使用类似双向锁或者是原子操作的东西,但是这样挺难弄而且容易出错。

使用GCD,我们可以这样重写上面的方法,使用函数 dispatch_once

    + (id)sharedWhatever
{
static dispatch_once_t pred;
static Whatever *whatever = nil;
dispatch_once(&pred, ^{
whatever = [[Whatever alloc] init];
});
return whatever;
}

这个稍微比 @synchronized方法简单些,并且GCD确保以更快的方式完成这些检测,它保证block中的代码在任何线程通过  dispatch_once 调用之前被执行,但它不会强制每次调用这个函数都让代码进行同步控制。实际上,如果你去看这个函数所在的头文件,你会发现目前它的实现其实是一个宏,进行了内联的初始化测试,这意味着通常情况下,你不用付出函数调用的负载代价,并且会有更少的同步控制负载。

iOS单例的两种实现的更多相关文章

  1. objc单例的两种安全实现方案

    所有转出博客园,请您注明出处:http://www.cnblogs.com/xiaobajiu/p/4122034.html objc的单例的两种安全实现方案 首先应该知道单例的实现有两大类,一个是懒 ...

  2. iOS 创建单例的两种方法

    创建一个单例很多办法.我先列举一个苹果官方文档中的写法. [cpp] view plaincopy static AccountManager *DefaultManager = nil; + (Ac ...

  3. 【iOS开发】创建单例的两种方法

    创建一个单例很多办法.我先列举一个苹果官方文档中的写法. [cpp] view plaincopy   static AccountManager *DefaultManager = nil; + ( ...

  4. IOS创建单例的两种方法

    1.0  苹果官方写法:  static AccountManager *DefaultManager = nil; + (AccountManager *)defaultManager { if ( ...

  5. ios 单例的再次理解

    单例模式    在建模的时候,如果这个东西确实只需要一个对象,多余的对象都是无意义的,那么就考虑用单例模式.比如定位管理(CLLocationManager),硬件设备就只有一  个,弄再多的逻辑对象 ...

  6. 【iOS 单例设计模式】底层解析与运用

    [iOS 单例设计模式]底层解析与运用 一.单例设计名词解释: (官方解释)单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例.(形象比喻)程序 — 公司   单例实例 - 管理 ...

  7. java单例的几种实现方法

    java单例的几种实现方法: 方式1: public class Something { private Something() {} private static class LazyHolder ...

  8. iOS开发笔记-两种单例模式的写法

    iOS开发笔记-两种单例模式的写法   单例模式是开发中最常用的写法之一,iOS的单例模式有两种官方写法,如下: 不使用GCD #import "ServiceManager.h" ...

  9. IOS文件操作的两种方式:NSFileManager操作和流操作

    1.常见的NSFileManager文件方法 -(NSData *)contentsAtPath:path //从一个文件读取数据 -(BOOL)createFileAtPath: path cont ...

随机推荐

  1. Linq打印

    Method syntax: Enumerable.Range(1, 100).ToList().ForEach(Console.WriteLine); Query syntax: (from n i ...

  2. Candies(差分约束)

    http://poj.org/problem?id=3159 题意: flymouse是幼稚园班上的班长,一天老师给小朋友们买了一堆的糖果,由flymouse来分发,在班上,flymouse和snoo ...

  3. IOS7官方推荐图标和图像尺寸

    图标和图像大小 每一个应用程序需要一个应用程序图标和启动图像.此外,一些应用程序需要自定义的图标来表示特定于应用程序的内容,功能,或在导航栏,工具栏和标签栏模式. 不像其他的定制艺术品在您的应用程序的 ...

  4. unity5 人皮渲染 Skin Shading

    换了一种方法,优化了一下代码,unity5效果很好,消耗不大 点开可查看大图 加入了次表面散射的阴影与自阴影              ------------by wolf96  wolf_crix ...

  5. poj 3575 Crosses and Crosses(SG函数)

    Crosses and Crosses Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 3063   Accepted: 11 ...

  6. OpenStack网络的前世今生

    声明: 本文转自OpenStack中国社区,原文链接:http://www.openstack.cn/p353.html,作者Joshua,转载请注明. 在OpenStack世界中,网络组件最初叫no ...

  7. hibernate学习之Hibernate API

    1. Hibernate Api分类 1)提供访问数据库的操作(如保存,更新,删除,查询)的接口.这些接口包括:Session, Transaction,,Query接口. 2)由于配置Hiberna ...

  8. java 深clone和浅clone

    1. clone类 public class Person implements Cloneable, Serializable{ /** * */ private static final long ...

  9. ng-repeat 遍历同值数组导致的报错

    http://blog.csdn.net/tyust512/article/details/50370624

  10. js事件的方法

    事件的方法:onclick         鼠标单击ondblclick       鼠标双击onkeyup         按下并释放键盘上的一个键时触发 onchange        文本内容或 ...