一、概述:

有一些对象我们只需要一个,比方说:线程池(threadpool)、缓存(cache)、对话框、处理偏好设置和注册表对象、日志对象、充当打印机、显卡等设备的驱动程序的对象。事实上这些对象只需要一个实例,如果制造出多个实例就会导致很多问题发生。(利用静态类变量、静态方法和适当的访问修饰符的确也可以做到只存在一个实例。)

苏格拉底诱导式回答:(参考《Head First 设计模式》)

如何创建一个对象? new MyObject()
万一另外一个对象想创Myobject会怎样?可以再次new MyObject吗? 是的,当然可以。
所以一旦有一个类,我们是否都能多次的实例化它? 如果是公开的类 就可以
如果不是的话,会怎样?

如果不是公开的类,只有同一个包内的类可以实例化它,但是仍可以实例化它很多次

可以这么做吗?

public Myclass
{private Myclass(){}
}

 我没想过,但是这是合法的定义,有一定的道理。
 怎么说呢?  我认为含有私有的构造器类不能呗实例化。
 又可以使用私有的构造器对象吗?  恩,我想Myclass内的代码是唯一能调用此构造器的代码,但是这又不太合乎常理。
 WHY?  因为只有Myclass的实例才能调用Myclass的构造器,但是因为没有其他类能够实例化Myclass,所以我们得不到这样的实例。

嘿,我有个想法。

你认为如何?

public Myclass
{public static MyClass getInstance(){}
}

MyClass有一个静态方法,我们可以这样调用这个方法:

MyClas.getInstance();

 
 为何调用的时候用MyCLass类名,而不是对象名。  因为getInstance是类方法,是一个静态方法,你需要使用类名。

有意思,假如把这些合在一起“是否”就可以初始化一个MyClass?

public MyClass
{private MyClass(){}public static Myclass getInstance(){return new MyClass();}
}

当然可以 
 好了,你能想出第二种实例化对象的方式吗?  MyClass.getInstance();
 你能够完成代码是MyClass只有一个实例被产生吗?  恩,大概可以吧。。。。

单例模式优点

  1. 正如前面说的,单例模式在内存中只有一个实例,减少了内存开支。特别是一个对象需要频繁的创建、销毁时,而创建与销毁的性能有无法优化,单例模式的优势就非常明显。
  2. 单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。
  3. 单例模式可以避免对资源的多重占用。
  4. 单例模式可以在系统设置全局的访问点,优化和共享资源访问。

单例模式缺点

  1. 单例模式一般没有接口,扩展很困难,除了修改代码基本上没有第二种途径实现。
  2. 单例模式对测试是不利的。在并行开发环境中,如果单例模式没有完成,是不能进行测试的。
  3. 单例模式与单一职责原则有冲突。

二、在IOS中的应用

单例模式在iOS开发中的使用还是蛮多的,许多FoundationCocoaUIKit中的类都实现了单例模式,比如应用程序本身UIApplication、文件操作类NSFileManager、消息中心NSNotificitonCenter等系统都已经给我们实现单例,我们只需要使用就好了。在iOS中使用单例模式要使用类方法,通过类方法返回该类的唯一对象。

在ios中的应用主要有以下三种方式

1、

static Singleton *instance = nil;+ (Singleton *)sharedInstance
{if (instance == nil) {instance = [[super allocWithZone:NULL] init];}return instance;
}+ (id)allocWithZone:(NSZone *)zone
{return [[self sharedInstance] retain];
}- (id)copyWithZone:(NSZone *)zone
{return self;
}- (id)retain
{return self;
}- (NSUInteger)retainCount
{return NSUIntegerMax;  //denotes an object that cannot be released
}- (void)release
{//do nothing
}- (id)autorelease
{return self;
}

可以看到这种方式,使用静态成员维持了一个永久存在的对象,而且覆盖了alloc方法(alloc方法会调用allocWithZone:方法),并且也覆盖了所有与引用技术有关的方法,这都使这个对象不会被销毁。这样看上去基本实现了我们需要的,但是写起来麻烦不说,还有很大的一个问题,那就是多线程问题,如果是在多线程中那么该种方法就不能保证只产生一个对象了。所以这种方式只是介绍一下,并不推荐使用。

2、引入头文件

程序员都是偷懒的,现在流行使用一个宏定义来搞定这许多的事,而且考虑的更加周全。

单例包含以下接口

+ (MyClass*) sharedInstance; 
+ (void) purgeSharedInstance;

调用sharedInstance会创建并返回单例

调用purgeSharedInstance会销毁单例

手动调用alloc也可以保证是单例,你可以这样调用

[[MyClass alloc] initWithParam:firstParam secondParam:secondParam];

只是要保证在sharedInstance之前调用,因为只有一次创建机会。

下面是使用宏的写法“

MyClass.h:
======================================== #import "SynthesizeSingleton.h" @interface MyClass: SomeSuperclass { ... } SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(MyClass); @end
======================================== MyClass.m:
======================================== #import "MyClass.h" @implementation MyClass SYNTHESIZE_SINGLETON_FOR_CLASS(MyClass); ... @end
========================================

开源库下载地址

3、

iOS在4.0以后推出了blockGCD,这两个特性给iOS开发带来的很大的便利,也使开发变得更加趣味话。那么如何通过GCD+block来实现单例模式呢,这主要归功于dispatch_once(dispatch_once_t *predicate, ^(void)block)这个GCD的函数,他有两个参数第一参数是一个指向dispatch_once_t类型结构体的指针,用来测试block是否执行完成,该指针所指向的结构体必须是全局的或者静态的,第二个参数是一个返回值与参数均为空的block,在block体中进行对象的初始化即可。dispatch_once在程序的生命周期中保证只会被调用一次,所以在多线程中也不会有问题。 该种方法使用方法:

+ (Singleton *)sharedInstance
{static Singleton *instance = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{instance = [[Singleton alloc]init];});return instance;
}


dispatch_once的作用就是执行且在整个程序的声明周期中,仅执行一次某一个block对象。简直就是为单例而生的嘛。而且,有些我们需要在程序开头初始化的动作,如果为了保证其,仅执行一次,也可以放到这个dispatch_once来执行。

然后我们看到它需要一个断言来确定这个代码块是否执行,这个断言的指针要保存起来,相对于第一种方法而言,还需要多保存一个指针。

方法简介中就说的很清楚了:对于在应用中创建一个初始化一个全局的数据对象(单例模式),这个函数很有用。

如果同时在多线程中调用它,这个函数将等待同步等待,直至该block调用结束。

这个断言的指针必须要全局化的保存,或者放在静态区内。使用存放在自动分配区域或者动态区域的断言,dispatch_once执行的结果是不可预知的。

总结:1.这个方法可以在创建单例或者某些初始化动作时使用,以保证其唯一性。2.该方法是线程安全的,所以请放心大胆的在子线程中使用。(前提是你的dispatch_once_t onceToken

对象必须是全局或者静态对象。这一点很重要,如果不能保证这一点,也就不能保证该方法只会被执行一次。)


参考博客:

水滴石穿 Keeping faith.      --- wtlucky's Blog

转载于:https://www.cnblogs.com/ymonke/p/3513668.html

【设计模式】五、单例模式(独一无二的对象)相关推荐

  1. android 单例销毁,【设计模式与Android】单例模式——独一无二的皇帝

    什么是单例模式 所谓单例模式,就是确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例的设计模式.单例模式是最简单的设计模式,也是应用最广的设计模式.一般用于避免产生多个对象消耗过多的资源 ...

  2. Java23种设计模式之单例模式的五种实现方式、反射破解单例模式、不能破解枚举单例模式详解

    源码链接(Gitee码云):https://gitee.com/oldou/javadesignpatterns 这里有我整理好的Java23种设计模式的源码以及博客教程,博客教程中介绍了Java23 ...

  3. 单例模式——创建独一无二的对象

    1 概述 在我们的日常软件开发过程中,经常会发现某些对象在整个软件生命周期中,只需要创建一个实例,如果创建多个实例,可能导致许多问题出现,比如程序的行为异常.资源使用过量或者是不一致的结果等.像常见的 ...

  4. C#设计模式(1)——单例模式

    原文地址:http://www.cnblogs.com/zhili/p/SingletonPatterm.html 一.引言 最近在设计模式的一些内容,主要的参考书籍是<Head First 设 ...

  5. java设计模式之单例模式(七种方法)

    单例模式:个人认为这个是最简单的一种设计模式,而且也是在我们开发中最常用的一个设计模式. 单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个 ...

  6. Java设计模式之单例模式(Singleton Pattern)

    **单例模式:用来创造独一无二的,只能有一个实例的对象设计模式.单例模式确保一个类只有一个实例,并提供一个全局访问点.**相比于全局变量(对对象的静态引用),单例模式可以延迟实例化,而且全局变量不能保 ...

  7. 23种设计模式之单例模式、工厂模式、原型模式、建造者模式

    系列文章目录 第一章:程序设计原则-单一职责.接口隔离.依赖倒置.里式替换 第二章:程序设计原则-开闭原则.迪米特法则.合成复用原则 文章目录 系列文章目录 一.设计模式简单介绍 1.1.什么是设计模 ...

  8. 24种设计模式之单例模式

    24种设计模式之单例模式  一.核心作用: 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点. 二.常见的应用场景: 1.Windows的Task Manager(任务管理器)就是很典型的单 ...

  9. socket可以写成单例嘛_精读《设计模式 - Singleton 单例模式》

    Singleton(单例模式) Singleton(单例模式)属于创建型模式,提供一种对象获取方式,保证在一定范围内是唯一的. 意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 其实单例模 ...

  10. java单例模式的七种写法_Java设计模式之单例模式的七种写法

    什么是单例模式? 单例模式是一种常见的设计模式,单例模式的写法有很多种,这里主要介绍三种: 懒汉式单例模式.饿汉式单例模式.登记式单例 . 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类 ...

最新文章

  1. 【jquery】$.each的使用方法
  2. linux curl 命令模拟 http get post 请求
  3. wxWidgets:wxHeaderColumnSimple类用法
  4. emq+mysql设置_EMQ--添加mysql认证及mysql插件访问控制
  5. 通过改善架构来提高 ASP.Net 应用程序的性能
  6. opencv opencl加速_回放 | OpenCV Webinar 3:OpenCV深度学习应用与原理分析
  7. QT Core | 信号槽02 - GUI上按钮触发应用程序的函数(lambda表达式)
  8. 求树的直径(两种方法)
  9. (转载)Ubuntu如何进入图形界面
  10. 大数据行业到底有多少种工作岗位,各自的技能需求是什么?
  11. Ubuntu删除不干净导致的一系列后果
  12. 利用图片的 onerror 事件载入默认图片
  13. vofuria的开发(1)
  14. 有哪些好的网课软件推荐吗?3款实用学习软件蹭课必备
  15. 在thinkpad SL400上U盘安装双系统ubuntu14.10
  16. 写给大学男同胞的几条择偶建议
  17. matlab中clc什么意思,MATLAB中clc是什么意思
  18. EtherCAT从站协议栈代码笔记之ecat_def.h
  19. 【OR】S Lemma
  20. excel查重复_中小企业使用ERP管理软件与EXCEL的区别

热门文章

  1. docker-compose安装elk7.1.1版本
  2. C#调用Python模块
  3. Lecture 13 Amortized Analysis
  4. PostgreSQL 11 1Kw TPCC , 1亿 TPCB 7*24 强压耐久测试
  5. 锐捷亮相GITC:请互联网企业为我点个赞!
  6. 前端解决跨域问题的8种方案
  7. mysql 数据库授权(给某个用户授权某个数据库)
  8. nlp gpt论文_GPT-3:NLP镇的最新动态
  9. 白裤子变粉裤子怎么办_使用裤子构建构建数据科学的monorepo
  10. tableau 自定义省份_在Tableau中使用自定义图像映射