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

单例模式需要达到的目的

1. 封装一个共享的资源

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

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

单例模式的创建

简单创建方法:

@interface Singleton : NSObject  

+ (Singleton *) sharedInstance;  

@end  

在Singleton.m

@implementation Singleton    

static Singleton * sharedSingleton = nil;    

+ (Singleton *) sharedInstance  

{  

    if (sharedSingleton == nil) {  

        sharedSingleton = [[Singleton alloc] init];  

    }  

    return sharedSingleton;  

}  

@end  

严谨创建一个MySingletonClass的单例模式。首先,我们需要定义一个类MySingletonClass.

@interface MySingletonClass:NSObject {

}

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

 static MySingletonClass *sharedCLDelegate = nil;

+(MySingletonClass *)sharedInstance{
@synchronized(self) {
if(sharedCLDelegate == nil) {
[[[self class] alloc] init]; // assignment not done here
}
}
return sharedCLDelegate;
}

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

对实例化的控制

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

+ (id)hiddenAlloc
{
return [super alloc];
}

+ (id)alloc
{
NSLog(@"%@: use +sharedInstance instead of +alloc", [[self class] name]);
return nil;
}

+ (id)new
{
return [self alloc];
}

+(id)allocWithZone:(NSZone*)zone
{
return [self alloc];
}

- (id)copyWithZone:(NSZone *)zone
{ // -copy inherited from NSObject calls -copyWithZone:
NSLog(@"MySingletonClass: attempt to -copy may be a bug.");
[self retain];
return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone
{
// -mutableCopy inherited from NSObject calls -mutableCopyWithZone:
return [self copyWithZone:zone];
}

+(id)sharedInstance修改如下:

+ (MySingletonClass *)sharedInstance {
@synchronized(self) {
if (sharedCLDelegate == nil) {
[[[self class] hiddenAlloc] init]; // assignment not done here
}
}
return sharedCLDelegate;
}

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

单例的销毁

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

+ (void)attemptDealloc
{
if ([sharedCLDelegate retainCount] != 1)
return;

[sharedCLDelegate release];
myInstance = nil;
}

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

iOS中的单例模式应用

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

iOS4之后可以这样做

+ (AccountManager *)sharedManager
{
static AccountManager *sharedAccountManagerInstance = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
sharedAccountManagerInstance = [[self alloc] init];
});
return sharedAccountManagerInstance;
}

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

  1. iOS单例模式(Singleton)写法简析

    单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 1.单例模式的要点: 显然单例模式的要点有三个:一是某个类只能有一个实例: ...

  2. IOS单例模式(Singleton)

    IOS单例模式(Singleton)   单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 1.单例模式的要点: 显然单例模 ...

  3. IOS 单例模式的写法

    iOS的单例模式有两种官方写法,如下: 1)不使用GCD的方式 #import "Manager.h" static Manager *manager; @implementati ...

  4. iOS 单例模式 浅叙

    单例模式作用 可以保证在程序运行过程中,一个类只有一个实例,而且该实例易于供外界使用 从而方便地控制了实例个数,并节约系统资源 单例模式使用场合 在整个引用程序中,共享一份资源(这份资源只需要创建初始 ...

  5. ios 单例模式(懒汉式)

    1. 单例模式的作用 可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问 从而方便地控制了实例个数,并节约系统资源 2. 单例模式的使用场合 在整个应用程序中,共享一份资源(这份资源 ...

  6. IOS 单例模式的学习

    单例模式只能修改无法释放,直到程序结束. 我们下面一步一步来做一个单例模式程序 (1)单例一旦创建,是永远存在于内存中的,所以需要创建一个全局量 static MySingletonClass *sh ...

  7. iOS – 单例模式写一次就够了

    一. 单例模式简介 单例模式的作用 可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问 从而方便地控制了实例个数,并节约系统资源 单例模式的使用场合 在整个应用程序中,共享一份资源( ...

  8. iOS 单例模式简单实例

    单例模式主要实现唯一实例,存活于整个程序范围内,一般存储用户信息经常用到单例,比如用户密码,密码在登录界面用一次,在修改密码界面用一次,而使用单例,就能保证密码唯一实例.如果不用单例模式,init 两 ...

  9. iOS 单例模式 学习 "52个方法 第6章 45条 使用 dispath_once 来执行只需运行一次的线程安全代码"

    百度定义:单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例. 维基百科:在软件工程中,单例是一种用于实现单例的数学概念,即将 ...

随机推荐

  1. replaceCharactersInRange

    NSString 替换字符串中某一位置的文字  replaceCharactersInRange NSString 替换字符串中某一位置的文字 - (void)viewDidLoad { NSMuta ...

  2. JAVA图片相关

    有些图片后缀为jpg,但是实际格式却不是jpg,通过url下载图片字节.然后用ImageIO读取时,出现返回null的情况.出现这种情况,就需要使用webp-imageio.jar.(https:// ...

  3. ibatis动态sql配置启动时提示:The content of elements must consist of well-formed character data...

    ibatis动态sql配置启动时提示:The content of elements must consist of well-formed character data... 2012-07-18 ...

  4. Redis 笔记与总结1 安装部署

    NoSQL 使用场景: 1.对数据高并发读写 2.对海量数据的高效率存储和访问 3.对数据的高可扩展性和高可用性 Redis 通常被称为数据结构服务器,因为键可以包含字符串(strings).哈希(h ...

  5. unity3d 基于物理渲染的问题解决

    最近1个月做了unity 次世代开发的一些程序方面的支持工作,当然也是基于物理渲染相关的,主要还是skyshop marmoset的使用吧,他算是unity4.x版本 PBR的优秀方案之一了但在使用以 ...

  6. PHP测试用例练习

    本测试用例是一个判断三角形类型的练习测试用例,基于Netbeans 8.1IDE环境,和phpunit-5.2.10以及脚手架工具phpunit-skelgen-2.0.1.具体的环境搭建可参照: h ...

  7. 统计学习方法笔记 -- Boosting方法

    AdaBoost算法 基本思想是,对于一个复杂的问题,单独用一个分类算法判断比较困难,那么我们就用一组分类器来进行综合判断,得到结果,"三个臭皮匠顶一个诸葛亮" 专业的说法, 强可 ...

  8. static的作用,this(),super()用法

    1:static{}表示静态代码块:在java虚拟机(jvm)加载该类时,会执行这个代码块一次,静态代码块在new()对象之前就加载了 2: this()与surper()区别:surper()是从子 ...

  9. Windows 下 Nginx + PHP + Xdebug + PHPStorm 调试环境配置

    前期条件:安装好 Nginx.PHP.PHPStorm,使得可以正常访问 一.为 PHP 安装 Xdebug 到 Xdebug 的官网(http://xdebug.org/download.php)下 ...

  10. java CountDownLatch

    Listing -. Using a Countdown Latch to Trigger a Coordinated Start import java.util.concurrent.CountD ...