iOS设计模式之【单例】

在这里插入图片描述


一、单例概述

所谓单例就是确保在程序运行过程中只创建一个对象实例。

  • 为什么需要使用单例
  • 节省内存开销。如果某个对象需要被多个其它对象使用,那可以考虑使用单例,因为这样该类只使用一份内存资源。
  • 使用单例,可以确保其它类只获取类的一份数据(变量值)。
  • 特点
  • 保证在程序运行过程中,一个类只有一个实例。
  • 必须能够自行创建这个实例
  • 易于供外界使用。
  • 使用场合
  • 在整个应用场合中,共享一份资源(只需创建初始化一次)
    系统的[UIApplication sharedApplication]、[NSUserDefaults standardUserDefaults]、
  • 登陆界面、播放器、工具类文件下载等。

二、单例的实现

实现主要是围绕着一个目的,在内存中创建唯一一个实例。
下面两种方式都是保证通过[MKSingletonPattern shareInstance]或者[[MKSingletonPattern alloc] init]等方式创建或者copy、mutableCopy操作最后的地址是同一个,且线程安全的。

  • 一种方式
//使用static修饰全局变量主要是保证只有该文件可以使用,外界是没有办法使用的,防止外界将指针清空
//初始化一个被强指针指向的全局变量,保证在整个进程中单例对象不要释放
static MKSingletonPattern *_instance = nil;

+ (instancetype)shareInstance {
    
    return [[self alloc] init];
}
//alloc调用此方法分配内存空间,防止外部通过alloc init方式创建对象
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    //对请求的同一块内存资源加锁
    @synchronized (self) {
        if (_instance == nil) {
            _instance = [super allocWithZone:zone];
        }
    }
    return _instance;
}

//防止外部对单例对象copy操作产生不同实例,遵循NSCopying协议
- (id)copyWithZone:(nullable NSZone *)zone {
    return _instance;
}
//防止外部对单例对象mutableCopy操作产生不同实例,遵循NSMutableCopying协议
- (id)mutableCopyWithZone:(NSZone *)zone {
    return _instance;
}

外部调用和结果

    MKSingletonPattern *s1 = [MKSingletonPattern shareInstance];
    MKSingletonPattern *s2 = [MKSingletonPattern shareInstance];
    MKSingletonPattern *s3 = [[MKSingletonPattern alloc] init];
    MKSingletonPattern *s4 = [[MKSingletonPattern alloc] init];
    MKSingletonPattern *s5 = [[MKSingletonPattern shareInstance] copy];
    NSLog(@"\ns1--%p\ns2--%p\ns3--%p\ns4--%p\ns5--%p\n", s1, s2, s3, s4, s5);

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        MKSingletonPattern *single = [MKSingletonPattern shareInstance];
        MKSingletonPattern *single1 = [[MKSingletonPattern alloc] init];
        NSLog(@"shareInstance=%p------single1=%p", single, single1);
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        MKSingletonPattern *single = [MKSingletonPattern shareInstance];
        MKSingletonPattern *single1 = [[MKSingletonPattern alloc] init];
        NSLog(@"shareInstance=%p------single1=%p", single, single1);
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
       MKSingletonPattern *single = [MKSingletonPattern shareInstance];
       MKSingletonPattern *single1 = [[MKSingletonPattern alloc] init];
       NSLog(@"shareInstance=%p------single1=%p", single, single1);
    });
s1--0x600001b594b0
s2--0x600001b594b0
s3--0x600001b594b0
s4--0x600001b594b0
s5--0x600001b594b0

shareInstance=0x600001b594b0------single1=0x600001b594b0
shareInstance=0x600001b594b0------single1=0x600001b594b0
shareInstance=0x600001b594b0------single1=0x600001b594b0
  • GCD方式

只需要在allocWithZone方法中添加一次性代码

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}

防止调用 alloc]init]引起的错误
防止调用 new 引起的错误
防止调用 copy 引起的错误(应该不常用)
防止调用 mutableCopy 引起的错误(应该不常用)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值