单例模式用于当一个类只能有一个实例的时候, 通常情况下这个“单例”代表的是某一个物理设备比如打印机,或是某种不可以有多个实例同时存在的虚拟资源或是系统属性比如一个程序的某个引擎或是数据。用单例模式加以控制是非常有必要的。

单例模式需要达到的目的

1. 封装一个共享的资源

2. 提供一个固定的实例创建方法

3. 提供一个标准的实例访问接口

单例模式的创建

本文以创建一个MySingletonClass的单例模式为例。首先,我们需要定义一个类MySingletonClass.

  1. @interface MySingletonClass:NSObject {
  2. }

并且为其添加一个类方法(注意,这里不是实例方法)+(id)sharedInstance;一个基本的实现写法如下:

  1. static MySingletonClass *sharedCLDelegate = nil;
  2. +(MySingletonClass *)sharedInstance{
  3. @synchronized(self) {
  4. if(sharedCLDelegate == nil) {
  5. [[[self class] alloc] init]; //   assignment   not   done   here
  6. }
  7. }
  8. return sharedCLDelegate;
  9. }

在上面的代码中(用到了关键字@synchronized是为了保证我们的单例的线程级别的安全,可以适用于多线程模式下。)static变量sharedCLDelegate用于存储一个单例的指针,并且强制所有对该变量的访问都必须通过类方法   +(id)sharedInstance,在对
  +(id)sharedInstance第一次调用时候完成实例的创建。这里值得留意一下的是,上面代码中用的是[[selfclass] alloc],而不是
[MySingletonClass alloc],一般情况下这两种写法产生同样的效果,但是这里这样做是为了更好的利用OOP的性质,[selfclass]可以动态查找并确定类的类型从而便于实现对该类的子类化。

对实例化的控制

为了完全的实现实例的单态性,必须通过一定手段来避免实例多次被创建。+(id)sharedInstance控制了单例的创建和访问,但是并不能控制其它地方的代码通过alloc方法来创建更多的实例,因此我们还要重载任何一个涉及到allocation的方法,这些方法包括
  +new, +alloc,+allocWithZone:, -copyWithZone:,
以及 -mutableCopyWithZone: 另外,+(id)sharedInstance也需要稍作修改。

  1. + (id)hiddenAlloc
  2. {
  3. return [super alloc];
  4. }
  5. + (id)alloc
  6. {
  7. NSLog(@"%@: use +sharedInstance instead of +alloc", [[self class] name]);
  8. return nil;
  9. }
  10. + (id)new
  11. {
  12. return [self alloc];
  13. }
  14. +(id)allocWithZone:(NSZone*)zone
  15. {
  16. return [self alloc];
  17. }
  18. -   (id)copyWithZone:(NSZone *)zone
  19. {   // -copy inherited from NSObject calls -copyWithZone:
  20. NSLog(@"MySingletonClass: attempt to -copy may be a bug.");
  21. [self retain];
  22. return self;
  23. }
  24. - (id)mutableCopyWithZone:(NSZone *)zone
  25. {
  26. // -mutableCopy inherited from NSObject calls -mutableCopyWithZone:
  27. return [self copyWithZone:zone];
  28. }
  29. +(id)sharedInstance修改如下:
  30. + (MySingletonClass *)sharedInstance {
  31. @synchronized(self) {
  32. if (sharedCLDelegate == nil)   {
  33. [[[self class] hiddenAlloc] init]; // assignment not done here
  34. }
  35. }
  36. return sharedCLDelegate;
  37. }

如果不考虑类的子类化,+hiddenAlloc这个方法可以省略。由于我们是用[selfclass]来实现类型的动态识别,用[[selfclass]
hiddenAlloc]可以避免调用到被重载过的alloc方法。此外,hiddenAlloc也为可能的子类化提供了一个调用原始alloc方法的机会。上面重载过的alloc方法只是给出一个log信息并且返回nil。Copying方法里只是简单的增加了retain的计数并没有返回一个新的实例。这也正体现了单例模式的性质,因为技术上来讲,拷贝一个单例是错误的(因为是“单例”)所以在copyWithZone方法中我们给出了一个错误信息,当然也可以扔出一个exception。

单例的销毁

通常我们在   -(void)applicationWillTerminate:(UIApplication *)application方法中调用如下方法:

  1. + (void)attemptDealloc
  2. {
  3. if ([sharedCLDelegate retainCount] != 1)
  4. return;
  5. [sharedCLDelegate release];
  6. myInstance = nil;
  7. }

值得注意的是,上面这个attemptDealloc方法顾名思义,只是试图释放掉这个单例。如果retain的计数不为1,说明还有其他地方对该单例发送过retain消息。考虑到一个单例模式的生存周期是整个程序结束为止。所以,在程序的任何一个地方都没有必要向这个单例发送retain消息,即便是对这个单例有引用。而是调用sharedInstance方法来引用这个单例,这样做是安全的,也是合乎单例模式的技术含义的。

iOS中的单例模式应用

iOS中好几个类都是采用了单例模式,比如NSApplication, NSFontManager,   NSDocumentController,NSHelpManager, NSNull,NSProcessInfo, NSScriptExecutionContext,   NSUserDefaults.

如果本文有任何错误之处,欢迎拍砖指正,共同进步, 谢谢!

iOS设计模式——单例模式的更多相关文章

  1. iOS设计模式-单例模式

    (一)什么是单例模式(Singleton) 单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点 *最初的定义是在<设计模式>(Addison-Wesley)中 解读 1> ...

  2. IOS设计模式之一(MVC模式,单例模式)

    iOS 设计模式-你可能已经听说过这个词,但是你真正理解它意味着什么吗?虽然大多数的开发者可能都会认为设计模式是非常重要的,然而关于设计模式这一主题的文章却不多,并且有时候我们开发者在写代码的时候也不 ...

  3. iOS设计模式(02):单例模式

    iOS设计模式(02):单例模式 singleton-design-pattern 什么是单例模式? 单例模式是一个类在系统中只有一个实例对象.通过全局的一个入口点对这个实例对象进行访问.在iOS开发 ...

  4. IOS设计模式浅析之单例模式(Singleton)

    说在前面 进入正式的设计模式交流之前,扯点闲话.我们在项目开发的过程中,经常会不经意的使用一些常见的设计模式,如单例模式.工厂方法模式.观察者模式等,以前做.NET开发的时候,认真拜读了一下程杰老师的 ...

  5. iOS书摘之Objective-C编程之道 iOS设计模式解析

    来自<Objective-C编程之道iOS设计模式解析>一书的摘要总结 一.Prototype 原型模式 定义:使用原型实例指定创建对象的种类,并通过复制这个原型创建新的对象.(<设 ...

  6. iOS 设计模式

    很赞的总结 iOS Design Patterns 中文版 IOS设计模式之一(MVC模式,单例模式) IOS设计模式之二(门面模式,装饰器模式) IOS设计模式之三(适配器模式,观察者模式) IOS ...

  7. iOS设计模式 - (1)概述

    近期可自由安排的时间比較多, iOS应用方面, 没什么好点子, 就先放下, 不写了.花点时间学学设计模式. 之后将会写一系列博文, 记录设计模式学习过程. 当然, 由于我自己是搞iOS的, 所以之后设 ...

  8. iOS 的单例模式 dispatch_once

    iOS 的单例模式 dispatch_once 有些变量仅仅须要初始化一次(如从文件里读取配置參数.读取设备型号等等),能够使用dispatch_once来进行读取优化.保证仅仅调用API一次,以后就 ...

  9. 【设计模式】Java设计模式 - 单例模式

    [设计模式]Java设计模式 - 单例模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 分享学习心得,欢迎指正,大家一起学习成长! 原创作品,更多关注我CSDN: ...

随机推荐

  1. crt 糟心的配置

    每次要下载安装crt就要捣鼓半天,各种注册机下来各种问题,顺手记录下刚打通的一个 1.crt 下载 网上看了一遍博客: SecureCRT 7.3.4破解版(含注册机), 下载下来后里面其实是不含注册 ...

  2. Wafer管芯数量及成本估算

    芯片流片费用一般不按颗数计价,现在流片主要分为全晶圆和MPW两种方式.   MPW是现在很流行的一种tapout方法,主要是按晶圆面积来均分价格.   如果是整个wafer的话,成本主要是wafer费 ...

  3. nodejs微信开发获取token,ticket-1

    /* jshint -W079 */ /* jshint -W020 */ "use strict"; var _ = require("lodash"); v ...

  4. BadUSB的防范研究

    近期爆出的badUSB漏洞,通过将病毒植入固件,能够伪装成键盘等设备,直接控制电脑,业界还没有非常好的修复方法. 从安全产品的角度.对于这个问题的防范,有下面几点可能不成熟的想法 1.病毒伪装成键盘. ...

  5. Android的MVC框架

    http://www.cnblogs.com/wanghafan/archive/2012/07/20/2600786.html MVC是当前比较流行的框架,随便Google下,就可以发现几乎所有的应 ...

  6. dataset 用法(2)

    1.为DataTable添加列 (1)添加列 DataTable  tbl = ds.Tables.Add("User"); DataColumn col =tbl.Columns ...

  7. JavaScript 开发经验整理

    前言 今年接触了一个B/S的项目,总结了一些JavaScript开发经验,整理些有用的内容与大家分享. 本文会持续更新... 1.实现代码访问的控制 随着项目JavaScript代码库扩大,本应被控制 ...

  8. .NET读取Project 2007 MPP项目文件

    Project文件读取: 方法1:Microsoft.Project.OLEDB.11.0 string strConn = "Provider=Microsoft.Project.OLED ...

  9. su Authentication failure解决

    su Authentication failure解决 关于Ubuntu桌面系统su root时认证失败的问题 1. Ubuntu 默认没有给root用户设置密码,当我们su root命令时, 提示认 ...

  10. 认识jeecms开源项目

    1. JEECMS源代码基本结构及相关技术简介: 参考:http://blog.csdn.net/caozhenyu/article/details/47005623