单例的意思从字面上就可以略知一二,所谓单例就是确保在程序运行过程中只创建一个对象实例。可以用于需要被多次广泛或者说多次使用的资源中,比如我们常见的网络请求类、工具类以及其它管理类等。比如我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. pysam - 多种格式基因组数据(sam/bam/vcf/bcf/cram/…)读写与处理模块(python)

    在开发基因组相关流程或工具时,经常需要读取.处理和创建bam.vcf.bcf文件.目前已经有一些主流的处理此类格式文件的工具,如samtools.picard.vcftools.bcftools,但此 ...

  2. centos下vsftpd安装与配置

    1.已经配置好可以上网了,所以即可通过yum install vsftpd安装啦.如果不能上网则可以通过dvd2.iso工具集rpm方式进行安装. 2.安装好后,默认本地可以通过匿名用户登录,但是其它 ...

  3. 串行通讯之Qt

    目录 第1章 Qt 串行通讯    1 1.1 配置.pro文件    1 1.2 查询串口信息    1 1.3 配置.打开串口    3 1.4 setRequestToSend在Windows上 ...

  4. java复用和传参

    java复用和传参的三种方法总结: (1) 直接在一个类中调用函数 : 1 package test1; 2 3 public class a 4 { 5 public static void get ...

  5. sql server 导出数据到 Azure Hbase / Hive 详细步骤

    The Hadoop on Azure Sqoop Import Sample Tutorial Table of Contents   Overview   Goals Key technologi ...

  6. 35 个免费创新的响应式 HTML5 模板

    HTML5 和响应式都是 Web 开发领域中的热门技术,本文向你推荐 35 个免费的响应式 HTML5 模板,将两种技术完美结合. Mori responsive HTML5 Template Res ...

  7. SqlServer关闭与启用标识(自增长)列

    1 --添加新列 2 ALTER TABLE TABLENAME ADD ID int 3 --赋值 4 UPDATE TABLENAME SET ID = IDENTITY_ID 5 --删除标识列 ...

  8. android 模拟器 使用键盘的配置

    1 打开 android Manageer , 克隆一个设备 2.

  9. hdu 3172 Virtual Friends (映射并查集)

    Virtual Friends Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  10. 初学java之触发响应事件

    import java.awt.*; import javax.swing.*; import java.awt.event.*; class WindowActionEvent extends JF ...