IOS 单例

转载地址:http://blog.csdn.net/zhugq_1988/article/details/8568033


创建一个单例很多办法。我先列举一个苹果官方文档中的写法。

 

[cpp]  viewplain copy
  1. static AccountManager *DefaultManager nil;  
  2.    
  3. (AccountManager *)defaultManager  
  4.     if (!DefaultManager) DefaultManager [[self allocWithZone:NULL] init];  
  5.     return DefaultManager;  
  6.  

当然,在iOS4之后有了另外一种写法:

 

 

[cpp]  viewplain copy
  1. (AccountManager *)sharedManager  
  2.  
  3.         static AccountManager *sharedAccountManagerInstance nil;  
  4.         static dispatch_once_t predicate;  
  5.         dispatch_once(&predicate, ^{  
  6.                 sharedAccountManagerInstance [[self alloc] init];   
  7.         });  
  8.     return sharedAccountManagerInstance;  
  9.  

该写法来自  objcolumnist ,文中提到,该写法具有以下几个特性:

 

1. 线程安全。

2. 满足静态分析器的要求。

3. 兼容了ARC


然后我还有点好奇的是dispatch_once,这个函数,没见过啊。

于是就到官方的文档里找找看,是怎么说的。

下面是官方文档介绍:

 

dispatch_once

Executes a block object once and only once for the lifetime of anapplication.

  void dispatch_once(

    dispatch_once_t*predicate,

    dispatch_block_t block);

Parameters

predicate

A pointer to a dispatch_once_t structure that is usedto test whether the block has completed or not.

block

The block object to execute once.

Discussion

This function is useful for initialization of global data(singletons) in an application. Always call this function beforeusing or testing any variables that are initialized by theblock.

If called simultaneously from multiple threads, this function waitssynchronously until the block has completed.

The predicate must point to a variable stored in global or staticscope. The result of using a predicate with automatic or dynamicstorage is undefined.

Availability

  • Available in iOS 4.0 and later.

Declared In

dispatch/once.h


我们看到,该方法的作用就是执行且在整个程序的声明周期中,仅执行一次某一个block对象。简直就是为单例而生的嘛。而且,有些我们需要在程序开头初始化的动作,如果为了保证其,仅执行一次,也可以放到这个dispatch_once来执行。

然后我们看到它需要一个断言来确定这个代码块是否执行,这个断言的指针要保存起来,相对于第一种方法而言,还需要多保存一个指针。


方法简介中就说的很清楚了:对于在应用中创建一个初始化一个全局的数据对象(单例模式),这个函数很有用。

如果同时在多线程中调用它,这个函数将等待同步等待,直至该block调用结束。

这个断言的指针必须要全局化的保存,或者放在静态区内。使用存放在自动分配区域或者动态区域的断言,dispatch_once执行的结果是不可预知的。



总结:1.这个方法可以在创建单例或者某些初始化动作时使用,以保证其唯一性。2.该方法是线程安全的,所以请放心大胆的在子线程中使用。(前提是你的dispatch_once_t*predicate对象必须是全局或者静态对象。这一点很重要,如果不能保证这一点,也就不能保证该方法只会被执行一次。)


单例模式作为一种目标明确、结构简单、理解容易的设计模式,在软件开发中使用频率相当高,在很多应用软件和框架中都得以广泛应用。

 

1.主要优点

      单例模式的主要优点如下:

      (1)单例模式提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它。

      (2)由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能。

      (3)允许可变数目的实例。基于单例模式我们可以进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例,既节省系统资源,又解决了单例单例对象共享过多有损性能的问题。

 

2.主要缺点

      单例模式的主要缺点如下:

      (1) 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。

      (2)单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。

      (3) 现在很多面向对象语言(JavaC#)的运行环境都提供了自动垃圾回收的技术,因此,如果实例化的共享对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致共享的单例对象状态的丢失。

 

3.适用场景

      在以下情况下可以考虑使用单例模式:

      (1)系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器或资源管理器,或者需要考虑资源消耗太大而只允许创建一个对象。

      (2)客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值