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

单例模式需要达到的目的

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. MySQL AUTO_INCREMENT 简介

    可使用复合索引在同一个数据表里创建多个相互独立的自增序列,具体做法是这样的:为数据表创建一个由多个数据列组成的PRIMARY KEY OR UNIQUE索引,并把AUTO_INCREMENT数据列包括 ...

  2. SQL Server save transaction

    准备: create table Nums(X int); 目的:只向表中插入一行. --------------------------------------------------------- ...

  3. 让两个Div并排显示

    一.使用display的inline属性 <div style="width:300px; height:auto; float:left; display:inline"& ...

  4. android ndk jni 环境搭建

    关于ndk jni网上的介绍很多,其实我了解这个主要是因为自己是做嵌入式的,一则是对C语音有感情  二则是知道jni  可以绕过framework 框架直接操作硬件抽象层. 1.概述 对于ndk, j ...

  5. Office 2010 Toolkit and EZ-Activator

    “Office 2010 Toolkit 2.0.1”是“迷你KMS”的更新换代版本.虽然是单一可执行程序,但一身承担两大职能:“KMS服务器”和“客户激活端”.“Office 2010 Toolki ...

  6. 深入解析SSD中MLC与SLC的性能差异

    固态硬盘(Solid State Disk或Solid State Drive),也称作电子硬盘或者固态电子盘,是由控制单元和固态存储单元(DRAM或FLASH芯片)组成的硬盘. 固态硬盘的接口规范和 ...

  7. 排序-java

    今天座右铭----每天的学习会让我们不断地进步! 往往面试中都会让我们用一种排序方法做一道排序题,下面我就罗列出快速排序.冒泡排序.插入排序.选择排序的java代码! 1.快速排序 public cl ...

  8. at org.apache.jsp.index_jsp._jspInit(index_jsp.java:23)异常解决

    部署项目,启动tomcat一切正常.输入项目地址后 tomcat报例如以下错误: java.lang.NullPointerException at org.apache.jsp.index_jsp. ...

  9. phpExcel在封装

    <?php /** * 数组生成Excel * @author zouhao zouhao619@gmail.com * 使用示例 * $excel =new Excel(); $data=ar ...

  10. 用ADB(Android Debug Bridge)实时监测Android程序的运行

      监控Android设备上程序的运行,需要ADB的配合,具体ADB工具的介绍以及命令选项可见博客: http://blog.csdn.net/mliubing2532/article/details ...