单例模式的初步学习

做这么久的项目,却没有总结的习惯。再这样下去,注定成不了好的程序员

什么是单例 :

Ensure a class only has one instance,and provide a global point of access to。它的主要特点不是根据客户程序调用生成一个新的实例,而是控制某个类型的实例数量-唯一一个。(《设计模式-基于C#的工程化实现及扩展》,王翔)。也就是说,单例模式就是保证在整个应用程序的生命周期中,在任何时刻,被指定的类只有一个实例,并为客户程序提供一个获取该实例的全局访问点。
特点:
1,一个类只能有一个实例;
2,自己创建这个实例;
3,整个系统都要使用这个实例。

苹果官方单例代码:具体点击链接

#import
'''
/* Singleton.h */
#import <Foundation/Foundation.h>
@interfaceSingleton:NSObject
+(Singleton*)instance;
@end
/* Singleton.m */
#import "Singleton.h"
staticSingleton*instance=nil;
@implementationSingleton
+(Singleton*)instance
{
    if(!instance)
{
instance=[[superallocWithZone:NULL]init];
}
  returnin stance;
}
+(id)allocWithZone:(NSZone*)zone
{
  return [self instance];
}
-(id)copyWithZone:(NSZone*)zone
{
return self;
}
-(id)init{
if(instance)
{
return instance;
}
  self=[super init];
  return self;
}
-(id)retain{
  return self;
}
-(oneway void)release
{
  // Do nothing
}
-(id)autorelease{
return self;
}
-(NSUInteger)retainCount
{
return  NSUIntegerMax;
}
@end

参考来源

为什么用单例:

单例的意图是为了保证一个类只有一个实例,并提供访问它的唯一全局访问点。之前一直在想,如果要完成这样的功能,其实全局变量也可以做到,不是吗?只要一个全局变量,然后在各个需要的地方调用这个全局变量即可,必要的时候可以extern,一样也可以完成这样的功能。那么,为什么不直接使用全局变量,而要搞一个单例出来?单例到底比全局变量好在哪儿?首先,全局变量不能保证全局只有一个类的实例,你完全可以声明同一个类的多个实例。当然,如果你注意一点,那么用全局方法保证全局只有一个该类的实例还是可以做到的,但你得很注意,让自己不要在其他地方声明多一个实例。而单例却可以轻松的做到这一点,并能保证全局只有一个该类的实例可被访问。其次,相对来说,使用单例时,代码会显得优雅一些。
单例模式与全局变量的详细比较
单例模式的其他应用场景

什么时候用单例

单例的使用主要是在需要保证全局只有一个实例可以被访问的情况,比如[系统]日志的输出、[操作系统]的任务管理器等。
一些细节
通常,我们看到的单例类没有析构函数,那么new出来的[空间]是怎么释放的呢?一般有2种做法,一种是不做任何操作,等最后程序结束时操作系统回收[资源];另外一种是另外搞一个函数或者类,来处理delete操作。对于像我这样的初级使用学者,还是选择第一种更方便,第二种相对来说需要考虑更多一些。

两种经典的多线程单例写法

 一、经典模式:
publicclass Singleton
{
privatestatic Singleton instance;
private Singleton()
{}
publicstatic Singleton GetInstance()
{
  if(instance==null)
{
  instance=new Singleton();
}
  return instance;
}


  解析如下:
  1)首先,该Singleton的构造函数必须是私有的,以保证客户程序不会通过new()操作产生一个实例,达到实现单例的目的;
  2)因为静态变量的生命周期跟整个应用程序的生命周期是一样的,所以可以定义一个私有的静态全局变量instance来保存该类的唯一实例;
  3)必须提供一个全局函数访问获得该实例,并且在该函数提供控制实例数量的功能,即通过if语句判断instance是否已被实例化,如果没有则可以同new()创建一个实例;否则,直接向客户返回一个实例。
  在这种经典模式下,没有考虑线程并发获取实例问题,即可能出现两个线程同时获取instance实例,且此时其为null时,就会出现两个线程分别创建了instance,违反了单例规则。因此,需对上面代码修改。
  二、多线程下的单例模式
  1、Lazy模式

publicclass Singleton
{
privatestatic Singleton instance;

private Singleton()
{

}

publicstatic Singleton GetInstance()
{
if(instance==null)
{
instance=new Singleton();
}
return instance;
}
}
  上述代码使用了双重锁方式较好地解决了多线程下的单例模式实现。先看内层的if语句块,使用这个语句块时,先进行加锁操作,保证只有一个线程可以访问该语句块,进而保证只创建了一个实例。再看外层的if语句块,这使得每个线程欲获取实例时不必每次都得加锁,因为只有实例为空时(即需要创建一个实例),才需加锁创建,若果已存在一个实例,就直接返回该实例,节省了性能开销。
  2、饿汉模式
  这种模式的特点是自己主动实例。
publicclass Singleton
{
privatestatic Singleton instance;
privatestaticobject _lock=newobject();

private Singleton()
{

}

publicstatic Singleton GetInstance()
{
if(instance==null)
{
lock(_lock)
{
if(instance==null)
{
instance=new Singleton();
}
}
}
return instance;
}
}

  上面使用的readonly关键可以跟static一起使用,用于指定该常量是类别级的,它的初始化交由静态构造函数实现,并可以在运行时编译。在这种模式下,无需自己解决线程安全性问题,CLR会给我们解决。由此可以看到这个类被加载时,会自动实例化这个类,而不用在第一次调用GetInstance()后才实例化出唯一的单例对象。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 单例模式(SingletonPattern)一般被认为是最简单、最易理解的设计模式,也因为它的简洁易懂,是项目中最...
    成热了阅读 9,852评论 4 34
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,675评论 19 139
  • 1 场景问题# 1.1 读取配置文件的内容## 考虑这样一个应用,读取配置文件的内容。 很多应用项目,都有与应用相...
    七寸知架构阅读 11,780评论 12 68
  • 前言 本文主要参考 那些年,我们一起写过的“单例模式”。 何为单例模式? 顾名思义,单例模式就是保证一个类仅有一个...
    tandeneck阅读 7,239评论 1 8
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 32,002评论 18 399