单例的意思从字面上就可以略知一二,所谓单例就是确保在程序运行过程中只创建一个对象实例。可以用于需要被多次广泛或者说多次使用的资源中,比如我们常见的网络请求类、工具类以及其它管理类等。比如我iOS开发中常见的系统单例[UIApplication sharedApplication]、[NSUserDefaults  standardUserDefaults]等。在iOS开发中,单例模式是非常有用的一种设计模式。如下图,是一个简单的例模式的UML类图。

一、使用单例模式的作用

它可以保证某个类在程序运行过程中最多只有一个实例,也就是对象实例只占用一份内存资源。

二、单例模式的三个要点:

  1. 该类有且只有一个实例;

  2. 该类必须能够自行创建这个实例;

  3. 该类必须能够自行向整个系统提供这个实例。

三、为什么需要使用单例

  1.节省内存开销。如果某个对象需要被多个其它对象使用,那可以考虑使用单例,因为这样该类只使用一份内存资源。

  2.使用单例,可以确保其它类只获取类的一份数据(变量值)。

四、单例模式优缺点

优点

  1、提供了对唯一实例的受控访问。

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

  3.因为单例模式的类控制了实例化的过程,所以类可以更加灵活修改实例化过程。

缺点

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

  2、单例类的职责过重,在一定程度上违背了“单一职责原则”。

五、单例的实现

基本步骤:

  (1) 为单例对象创建一个静态实例,可以写成全局的,也可以在类方法里面实现,并初始化为nil;

  (2) 实现一个实例构造方法,检查上面声明的静态实例是否为nil,如果是,则创建并返回一个本类的实例;

  (3) 重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不产生一个新实例;

  (4) 适当实现copyWithZone,mutableCopyWithZone,非arc下还需要实现release和autorelease方法。

下面我们来新建一个Singleton类,在Singleton.h中实现如下:

@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

  这样就创建一个简单的单例模式,实际上有一部分程序员也是这样实现的,但实际上这是一个不“严格”版本,在实际中使用,如果我们使用alloc,copy等方法创建对象时,依然会创建新的实例。而且如果多线程同时访问时候也会创建多个实例,因此这样做是非线程安全的。

下面我对Singleton.m的进行改进:

@implementation Singleton
static id sharedSingleton = nil;
+ (id)allocWithZone:(struct _NSZone *)zone
{
  if (_instace == nil) {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    sharedSingleton = [super allocWithZone:zone];
    });
  }
  return sharedSingleton;
} - (id)init
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedSingleton = [super init];
});
return sharedSingleton;
} + (instancetype)sharedInstance
{
   return [[self alloc] init];
} + (id)copyWithZone:(struct _NSZone *)zone
{   
  return sharedSingleton;
}
+ (id)mutableCopyWithZone:(struct _NSZone *)zone
{   
  return sharedSingleton;
}
@end

  这是一个比较完整的单例实现,这样在我们init,alloc,copy,mutableCopy时,都能保证只创建唯一单例。

六、把单例抽取成宏

  有时候我们一个程序会有多个单例,如果我们每个都去是有上面的代码,未免有些麻烦,因此我们可以讲上面的代码定义为宏,并保存在一个新文件中,然后就可以再任何需要实现单例模式的类中简单添加一两行代码就可以了。

  1.创建一个头文件Singleton.h,并添加如下代码:

// 帮助实现单例设计模式

// .h文件的实现
#define SingletonH(methodName) + (instancetype)shared##methodName; // .m文件的实现
#if __has_feature(objc_arc) // 是ARC
#define SingletonM(methodName) \
static id _instace = nil; \
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
if (_instace == nil) { \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [super allocWithZone:zone]; \
}); \
} \
return _instace; \
} \
\
- (id)init \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [super init]; \
}); \
return _instace; \
} \
\
+ (instancetype)shared##methodName \
{ \
return [[self alloc] init]; \
} \
+ (id)copyWithZone:(struct _NSZone *)zone \
{ \
return _instace; \
} \
\
+ (id)mutableCopyWithZone:(struct _NSZone *)zone \
{ \
return _instace; \
} #else // 不是ARC #define SingletonM(methodName) \
static id _instace = nil; \
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
if (_instace == nil) { \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [super allocWithZone:zone]; \
}); \
} \
return _instace; \
} \
\
- (id)init \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [super init]; \
}); \
return _instace; \
} \
\
+ (instancetype)shared##methodName \
{ \
return [[self alloc] init]; \
} \
\
- (oneway void)release \
{ \
\
} \
\
- (id)retain \
{ \
return self; \
} \
\
- (NSUInteger)retainCount \
{ \
return ; \
} \
+ (id)copyWithZone:(struct _NSZone *)zone \
{ \
return _instace; \
} \
\
+ (id)mutableCopyWithZone:(struct _NSZone *)zone \
{ \
return _instace; \
}

  2.这样我们在需要实现单例模式的类中轻易就可以实现单例模式了,假设有个工具类MJSoundTool。因此就可以这么做实现单例模式。

头文件MJSoundTool.h

#import <Foundation/Foundation.h>

#import "Singleton.h"

@interface MJSoundTool : NSObject

//+ (instancetype)sharedSoundTool;

SingletonH(SoundTool)

@end

实现文件MJSoundTool.m

#import "MJSoundTool.h"

@implementation MJSoundTool

SingletonM(SoundTool)

@end

  是不是很方便呢,我们以后需要设计单例的时候就可以直接使用该单例宏文件了。下载地址:单例宏Singleton.h。好了,单例模式就介绍到这里。

iOS开发之单例设计模式(完整正确版本)的更多相关文章

  1. IOS中的单例设计模式

    单例设计模式是IOS开发中一种很重要很常用的一种设计模式.它的设计原理是无论请求多少次,始终返回一个实例,也就是一个类只有一个实例.下面是苹果官方文档中关于单例模式的图片: 如图所示,左边的图是默认的 ...

  2. Java开发之单例设计模式

    设计模式之单例模式: 一.单例模式实现特点:①单例类在整个应用程序中只能有一个实例(通过私有无参构造器实现):②单例类必须自己创建这个实例并且可供其他对象访问(通过静态公开的访问权限修饰的getIns ...

  3. iOS 中的单例设计模式

    单例设计模式:在它的核心结构中只包含一个被称为单例类的特殊类.例如文件管理中的NSUserDefault,应用程序中的UIApplication,整个应用程序就这一个单例类,负责应用程序的一些操作,单 ...

  4. ios开发之 -- 单例类

    单例模式是一种软件设计模式,再它的核心结构中指包含一个被称为单例类的特殊类. 通过单例模式可以保证系统中一个类只有一个势力而且该势力易于外界访问,从而方便对势力个数的控制并节约系统资源.如果希望在系统 ...

  5. 【iOS 单例设计模式】底层解析与运用

    [iOS 单例设计模式]底层解析与运用 一.单例设计名词解释: (官方解释)单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例.(形象比喻)程序 — 公司   单例实例 - 管理 ...

  6. 牛客网Java刷题知识点之什么是单例模式?解决了什么问题?饿汉式单例(开发时常用)、懒汉式单例(面试时常用)、单例设计模式的内存图解

    不多说,直接上干货! 什么是单例设计模式? 解决的问题:可以保证一个类在内存中的对象唯一性,必须对于多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性. 如何保证? 1.不允许其他程序用new ...

  7. IOS设计模式第二篇之单例设计模式

    现在我们的组件已经有组织了.你需要从其他的地方得到数据,你也可以创建一个API类管理数据这个下个设计模式单例里面介绍. 这个单例设计模式确保这个类仅仅拥有一个实例,并且为这个实例提供一个全局的访问点. ...

  8. iOS 如何创建单例对象

    一.什么是单例? 说到单例我就想起了我的java啊 ,不禁感叹起我的大学时光,学了4年的java开发,到现在还是放弃了我的java,踏入了iOS的行列. 算了,入正轨,我现在正是铁树银花的青春美少女, ...

  9. JAVA学习第二十五课(多线程(四))- 单例设计模式涉及的多线程问题

    一.多线程下的单例设计模式 利用双重推断的形式解决懒汉式的安全问题和效率问题 //饿汉式 /*class Single { private static final Single t = new Si ...

随机推荐

  1. vim 空格和换行的删除和替换

      %s/\s//g %s/\r//g %s/\n//g   把一个很长的一行按空格分为多行 :%s/ +/\r/g简单解释一下:%s :在整个文件范围查找替换/ :分隔符+ :匹配空格,其中“ ”表 ...

  2. samtools常用命令详解(转)

    转自:samtools常用命令详解 samtools的说明文档:http://samtools.sourceforge.net/samtools.shtml samtools是一个用于操作sam和ba ...

  3. Hive中JOIN操作

    1. 只支持相等JOIN. 2. 多表连接当使用不同的列进行JOIN时,会产生多个MR作业. 3. 最后的表的数据是从流中读取,而前面的会在内存中缓存,因此最好把最大的表放在最后. SELECT /* ...

  4. Android相机开发那些坑

    版权声明:本文由王梓原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/168 来源:腾云阁 https://www.qclou ...

  5. java集合框架之java HashMap代码解析

     java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/arti ...

  6. JS获取页面元素并修改

    //实现代码如下,非常简单<script> (function(){ var ele = document.getElementsByTagName("ul"); // ...

  7. 《Java程序设计》学期总结

    <Java程序设计> 学期总结 课程设计小组 -迦瓦栈队 团队博客 读书笔记汇总 第一周 第二周 第三周 第四周 第五周 第六周 第七周 第八周 第九周 第十周 实验报告汇总 实验一 实验 ...

  8. 3.7 嵌入式SQL

    可以放入所有高级语言中去,如C 因为,SQL是过程性语句,需要高级语言的非过程性处理集合的分类处理 一.一般形式 所有的SQL语句都必须加前缀EXEC SQL SQL语句完成结束标志(:或END EX ...

  9. 用HTML5实现手机摇一摇的功能(转)

    在百度开发者大会上我介绍过HTML5另外一个重要特性就是DeviceOrientation,它将底层的方向传感器和运动传感器进行了高级封装,提供了DOM事件的支持.这个特性包括两种事件: 1.devi ...

  10. eval()函数使用

    条件:有数据集data[indx],数据集内含有对象data[index].obj1.pama1. 说明:传入参数为var str = 'obj1.pama1',要求取得data[index].obj ...