巧用Singleton(单例)

一.什么是单例设计模式

1、简单说明:

(1)永远只分配一块内存来创建对象,实现allocWithZone方法

(2)提供一个类方法,返回内部唯一的一个变量

2、单例模式说明

(1)单例模式的作用 :可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问,从而方便地控制了实例个数,并节约系统资源。

(2)单例模式的使用场合:在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次),应该让这个类创建出来的对象永远只有一个。


(3)单例模式在ARC\MRC环境下的写法有所不同,需要编写2套不同的代码

       可以用宏判断是否为ARC环境,后面的使用中会告诉你如何编写代码来适配两种不同的情况


二.在什么时候使用单例和使用单例的优缺点:



1.如果在项目中访问的是同一个对象,那么我们就应该提供一个全局的访问点给外界,此时使用单例可以减少对象的创建次数,节省内存的分配

2.创建单例对象可以高效的访问对象的方法,提高app的执行速率

3.定义单例对象更加符合苹果MVC的封装思想,体现出了高内聚,低耦合,代码更加简洁


缺点:

对象被创建以后,由于是单例对象(static修饰的对象),对象一旦创建就不会销毁,知道app完全意义上的退出才销毁对象

总结:

单例在项目中的是必不可少的,它可以使我们全局都可共享我们的数据。这只是简单的问题,大家根据自己的情况回答。

  • 首先,单例写法有好几种,通常的写法是基于线程安全的写法,结合dispatch_once来使用,保证单例对象只会被创建一次。如果不小心销毁了单例,再调用单例生成方法是不会再创建的。
  • 其次,由于单例是约定俗成的,因此在实际开发中通常不会去重写内存管理方法。

单例确实给我们带来的便利,但是它也会有代价的。单例一旦创建,整个App使用过程都不会释放,这会占用内存,因此不可滥用单例。


那么,同样作为工具类的使用,到底是使用单例还是类方法,这个就得看需求,如果说工具类不依赖任何属性的时候就是用类方法(类方法的使用在此就不展开说了)

三.如何实现单例

1.ARC下实现单例
//定义一份变量(整个程序运行过程中,只有一份)
+(instancetype)shareProductName{
    return [[self alloc]init];
}
//重写该方法,控制内存的分配,永远只分配一次存储空间
+(instancetype)allocWithZone:(struct _NSZone *)zone{
    static id instance = nil;
    //里面的代码只会执行一次,
    //补充:如果把代码下载dispatch_once里面,那么它内部默认会进行加锁。
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super allocWithZone:zone];
    });
    return instance;
}
-(instancetype)copyWithZone:(struct _NSZone *)zone{
    return self;
}

2.MRC下实现单例
项目默认环境是ARC环境,将ARC环境转换为MRC的操作如下图:

非ARC中(MRC),单例模式的实现(比ARC多了几个步骤)

实现内存管理方法

- (id)retain { return self; }

- (NSUInteger)retainCount { return 1; }

- (oneway void)release {}

- (id)autorelease { return self; }

//定义一份变量(整个程序运行过程中,只有一份)
+(instancetype)shareProductName{
    return [[self alloc]init];
}
//重写该方法,控制内存的分配,永远只分配一次存储空间
+(instancetype)allocWithZone:(struct _NSZone *)zone{
    static id instance = nil;
    //里面的代码只会执行一次,
    //补充:如果把代码下载dispatch_once里面,那么它内部默认会进行加锁。
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super allocWithZone:zone];
    });
    return instance;
}

-(oneway void)release{
    
}

-(instancetype)retain{
    return self;
}
-(instancetype)autorelease{
    return self;
}
-(NSUInteger)retainCount{
    return 1;
}

3、把单例代码定义为一个带参数的宏

1>.新的困扰

弊端:如果又创建一个新的类,是否又要把文件代码拷贝一份,所以这里可以考虑把固定的代码写成宏。

由于项目中代码经常有移植的需要,要求项目中又有ARC的,又有非ARC的,应该怎么应用单例模式?

不管项目是ARC的还是非ARC的,这个宏都有用。可以先判断编译器的环境,判断当前环境是否是ARC的。

条件编译的使用:


2>.使用条件编译,并把单例模式的代码定义为宏。

新建一个.h头文件


  

把代码定义为宏,头文件中的代码如下:

// ## : 连接字符串和参数
#define CRJSingleton_h(name) + (instancetype)share##name;

#if __has_feature(objc_arc)//arc环境
#define CRJSingleton_m(name) + (instancetype)share##name{\
return [[self alloc]init];\
}\
\
+(instancetype)allocWithZone:(struct _NSZone *)zone{\
static id instance = nil;\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken,^{\
instance = [super allocWithZone:zone];\
});\
return instance;\
}\
\
-(id)copyWithZone:(struct _NSZone *)zone{\
return self;\
}

#else
#define CRJSingleton_m(name) + (instancetype)share##name{\
return [[self alloc]init];\
}\
\
+(instancetype)allocWithZone:(struct _NSZone *)zone{\
static id instance = nil;\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken,^{\
instance = [super allocWithZone:zone];\
});\
return instance;\
}\
\
-(id)copyWithZone:(struct _NSZone *)zone{\
return self;\
}\
\
-(oneway void)release{\
\
}\
\
-(instancetype)retain{\
return self;\
}\
\
-(instancetype)autorelease{\
return self;\
}\
\
-(NSUInteger)retainCount{\
return 1;\
}
#endif


四.怎样用swift实现单例

swift创建单例的方式有好多种,下面我只写出最简洁的版本:

//在swift中的单例

class CRJSongleton: NSObject {
    
    // 常量保证只执行一次, let是线程安全的
    static let sharedInstance: CRJSongleton = CRJSongleton()
}

为什么swift中这么简单的一句话就可以实现单例呢?

1.static 修饰的变量/常量在创建以后就一直存在,知道程序真正意义上的退出才销毁,从而达到了对象可以随时调用

2.let 修饰的是不可变的常量,本身就是线程安全的,常量可以保证只赋值一次以后不能再被修改,等价于GCD中的只执行一次dispatch_once

综上所述,用swift实现单例就是这么滴简单,一句代码实现对象只允许被创建一次,且全局都可访问

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值