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

单例模式需要达到的目的

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. A线段树

    线段树专题 顾琪坤 1.简介: 打acm的时候,经常会碰到一类问题,比方给你n个数的序列,然后动态的更改某些数的值,然后又动态地询问某个区间的值的和或者其它乱七八糟的东西,对于单个更改或者询问,也许很 ...

  2. lucene 3.0.2 基本操作入门

    转自:Bannings http://blog.csdn.net/zhangao0086/article/details/ 我们为什么需要Lucene? 任何的的查询功能都类似,都是对文本内容的搜索, ...

  3. Win2003+Powershell2.0下无权限解锁账号

    在GE环境下,我通过图形界面ADUC可以解锁一个员工账号,但是通过powershell命令却提示权限不足,咋回事?   PS C:\Users\814072> Unlock-ADAccount ...

  4. SCU 2941 I NEED A OFFER!(01背包变形)

    I NEED A OFFER!     64bit IO Format: %lld & %llu Submit Status Description Description Speakless ...

  5. HDU 1166敌兵布阵+NOJv2 1025: Hkhv love spent money(线段树单点更新区间查询)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  6. Sql Group by 使用

    CREATE TABLE StuCourseScore ( ID int, Name nvarchar(10), Course nvarchar(10), Score int ) INSERT Stu ...

  7. VFS

    VFS的作用:为文件系统提供通用的接口. 通用文件模型:common file model.特殊文件系统需要将它的物理结构转换成通用文件模型. common file model包括以下几个重要对象: ...

  8. ExpandableListView实现子Item的点击事件

    在继承的BaseExpandableListAdapter的ExpandableListView的Adapter中,重写以下方法 @Override public boolean isChildSel ...

  9. 归纳整理 PHP大神的十大优良习惯

    2015年03月04日11:26 来源:程序师 作者:TECHUG 编辑:覃里 查看全文 赞(0)评论(0) 分享 标签: PHP , 编程指南 , PHP开源项目 [IT168 资讯] 1.多阅读手 ...

  10. buffer overflow vulnerabilitie

    Computer Systems A Programmer's Perspective Second Edition Avoiding security holes.For many years,bu ...