ios 单例模式详解

单例:在写项目的时候,我们实际用到了很多系统给我们提供的单例类;
如:

[UIApplication sharedApplication];  //应用程序实例类
[NSNotificationCenter defaultCenter];//消息中心实例类
[NSFileManager defaultManager];//文件管理实例类
[NSUserDefaults standardUserDefaults];//应用程序设置
[NSURLCache sharedURLCache];//请求缓存实例类

下面我们学习下单例:
一 、 单例的定义和生命周期

  • 单例类,在整个项目中只有一个实例,并提供一个类方法供全局调用,在编译时初始化这个类,然后一直保存在内存中,到程序退出时由系统自动释放这部分内存。

  • 一般在程序中,经常调用的类,如工具类、公共跳转类等都会采用单例模式;

  • 在程序中,一个单例类在程序中只能初始化一次,为了保证在使用中始终都是存在的,所以单例是在存储器的全局区域,在编译时分配内存,只要程序还在运行就会一直占用内存,在APP结束后由系统释放这部分内存内存。

二、单例的实现

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

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

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

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

代码实现 ------------1

  1. 首先定义一个LvSingleClass单例类

  2. 在 LvSingleClass.h文件中实现如下

     @interface LvSingleClass : NSObject
     + (LvSingleClass *)sharedSingleClass;
     @end
    
  3. 在LvSingleClass.m添加如下

    static LvSingleClass * singleClass = nil;
    
    + (LvSingleClass *)sharedSingleClass {
    //可以用synchronized
    //    @synchronized(self){
    //        if (singleClass == nil) {
    //            singleClass = [[LvSingleClass alloc]  init];
    //        }
    //    }
    //可以用dispatch_once
       static dispatch_once_t onceToken;
       dispatch_once(&onceToken, ^{
           singleClass = [[LvSingleClass alloc] init];
       });
       return singleClass;
    }
    
    - (id)init
    {
       static dispatch_once_t onceToken;
       dispatch_once(&onceToken, ^{
          singleClass = [super init];
       });
       return singleClass;
    }
    
    + (id)allocWithZone:(struct _NSZone *)zone {
       if (singleClass == nil) {
           static dispatch_once_t onceToken;
           dispatch_once(&onceToken, ^{
               singleClass = [super allocWithZone:zone];
           });
       }
       return singleClass;
    }
    
    + (id)copyWithZone:(struct _NSZone *)zone
    {
        return singleClass;
    }
    + (id)mutableCopyWithZone:(struct _NSZone *)zone
    {
        return  singleClass;
    }
    

//创建单例的时候可以用synchronized和dispatch_once 个人觉得用后者
  
这样一个比较完整的单例实现,这样在我们init,alloc,copy,mutableCopy时,都能保证只创建唯一单例。
例如 我们 NSLog(@"---%@----%@",[[LvSingleClass alloc] init], [LvSingleClass sharedSingleClass]); 调用打印
会发现 如下 地址是一样的

2018-10-31 11:01:39.779933+0800 Single[19695:5948562]
—<LvSingleClass: 0x60000000c150>----<LvSingleClass: 0x60000000c150>

还有另一种方法 ---------2

  1. 首先定义一个LvOtherSingleClass单例类

  2. 在 LvOtherSingleClass.h文件中实现如下

    + (LvOtherSingleClass *)sharedSingle;
    +(instancetype) new __attribute__((unavailable("单例类只能初始化一次")));
    -(instancetype) copy __attribute__((unavailable("单例类只能初始化一次")));
    -(instancetype) mutableCopy  __attribute__((unavailable("单例类只能初始化一次")));
    
  3. 在 LvOtherSingleClass.m文件中实现如下

    static LvOtherSingleClass * singleClass = nil;
    
    + (LvOtherSingleClass *)sharedSingle {
    //可以用synchronized和dispatch_once 个人觉得用后者
    //可以用synchronized
    //    @synchronized(self){
    //        if (singleClass == nil) {
    //            singleClass = [[LvOtherSingleClass alloc]  init];
    //        }
    //    }
    //可以用dispatch_once
       static dispatch_once_t onceToken;
       dispatch_once(&onceToken, ^{
           singleClass = [[LvOtherSingleClass alloc] init];
       });
       return singleClass;
    }
    
    +(void)initialize
    {
        [LvOtherSingleClass sharedSingle];
    }
    
    + (instancetype)alloc
    {
    //如果已经初始化了
       if(singleClass)
       {
          return  singleClass;
       }
       return [super alloc];
    }
    

这样一个比较完整的单例也实现,这样在我们new,copy,mutableCopy时,会找不到哪些方法。

三 、优缺点

优点
1、整个项目中只会实例化一次;
2、在整个项目中只实例化一个对象,节省系统内存,提高程序的运行效率
缺点
1、不能被重写、不能被继承、不能被扩展
2、创建单例对象之后,只要程序一直运行就一直占用这系统的内存,在不用该对象的时候也不能销毁消耗着系统的内存

csdn 下载demo

github 下载demo

猜你喜欢

转载自blog.csdn.net/u013983033/article/details/83415144