OC-单例模式

文章目录

单例模式

定义

单例模式,简单的说就是一个类始终只对应同一个对象,每次获取这个类的对象获得的都是同一个实例

如果一个类始终只能创建一个实例,那么这个类被称为单例类。单例类只有一个全局的接口来访问这个实例。当第一次载入的时候,他通常使用延迟加载的方创建唯一单例。在程序中一个单例只初始化一次,为了保证在使用中始终存在,单例类的存储是在存储器的全局区域,在编译时分配内存,只要程序在运行单例就始终存在,占用内存。在APP结束运行后释放这部分内存。但是在系统方法中,存在未知的自动释放池,如果对一个对象进行自动释放的话,可能进入未知的释放池,出现内存问题。即为单例模式不能自动释放的原因

特点

  1. 单例类是一个类,这个类创造出的对象是单例对象
  2. 单例对象使用类方法创建
  3. 单例一旦被创建出来,直到程序结束运行才会释放
  4. 单例不用我们来管理内存,内存会随着程序关闭而被释放

使用原因

节省内存,防止一个实例被重复创建从而占用内存空间。

缺点

  • 全局状态:可能导致全局状态的存在,使得程序难以调试,一个地方修改容易导致很多地方发生变化
  • 难以拓展:单例模式的实例是固定的,难以拓展以支持多个实例,必须修改代码,使单例类丢失单例的特性
  • 隐藏依赖关系:可能会隐藏单例类的依赖关系,代码更加耦合。

模式介绍

懒汉模式

是一种常见的单例设计模式,其主要特点是在需要时在创建单例对象的实现,通过延迟对象的初始化来节省资源和提高性能。适用于访问量较小的情况,使用时间来换取空间

同步锁实现
objectivec 复制代码
#import "Person.h"

@implementation Person
static id instance = nil;
+ (instancetype)sharedInstance {
    @synchronized (self) {
        if (!instance) {
            instance = [[super allocWithZone:NULL] init];
        }
    }
    return instance;
}
@end

这一段代码提供了一个全局访问点sharedInstace类方法提供给外部访问这个单例,在方法内部通过添加了一个同步锁,限制了同一时间只有一个线程访问临界区的代码。但是这里如果instance已经存在是没有必要进入锁的,所以可以再加个判断如下:

objectivec 复制代码
#import "Person.h"

@implementation Person
static id instance = nil;
+ (instancetype)sharedInstance {
    if (!instance) {
        @synchronized (self) {
            if (!instance) {
                instance = [[super allocWithZone:NULL] init];
            }
        }
    }
    return instance;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    if (!instance) {
        @synchronized (self) {
            if (!instance) {
                instance = [super allocWithZone:zone];
            }
        }
    }
    return instance;
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone {
    return self;
}
@end

对于allocWithZone的参数,传什么其实都无所谓,分配的内存区域不会改变

内层if的作用:假设有两个线程A和B同时调用了sharedInstance,线程A先一步获取锁,进入代码块,此时线程B等待锁释放,当线程A初始化instance后释放锁,B获得锁,如果没有内层if判断,会再次创建实例,破坏了单例的唯一性

dispatch_once

通过一个静态的dispatch_once变量来跟踪代码的执行状态,第一次调用时原子操作发现标记状态为未执行代码块,并原子性的将标记设为已执行,后续监测到标记为已执行,就会跳过该代码块。非常高效、没有阻塞开销

objectivec 复制代码
#import "Person.h"

@implementation Person
static id instance = nil;
+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[super allocWithZone:NULL] init];
    });
    return instance;
}

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

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone {
    return self;
}
@end

我们打印出不同情况下的对象地址如下:

饿汉模式

在类加载过程就完成这个单例的创建和初始化

实现
objectivec 复制代码
#import "Person.h"

@implementation Person
static id instance = nil;

+ (void)load {
    instance = [[super allocWithZone:NULL] init];
}

+ (instancetype)sharedInstance {
    return instance;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    return instance;
}

- (instancetype)init {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"init一次");
    });
    return self;
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone {
    return self;
}

@end

总结

懒汉模式

优点
  1. 延迟加载,节省资源,提高性能。
  2. 避免在程序启动时就创造不必要的对象,造成额外开销
  3. 可以通过加锁实现线程安全
缺点
  1. 为实现线程安全使用锁机制,可能会引起一些性能开销

饿汉模式

优点
  1. 实现简单,不需要考虑线程安全问题,实例在类加载时就已经创建了,所以不用考虑创建多个实例的风险
缺点
  1. 程序启动时就加载创建实例,可能会浪费资源,引起性能问题
  2. 如果单例对象的创建需要建立在某些外部前提下,那么不适合饿汉模式
相关推荐
2501_916008891 小时前
iOS应用开发工具全面解析:如何选择与优化开发效率
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
a4493153621 小时前
iPhone Face ID 故障的分层诊断——原深感系统与主板加密配对机制
macos·ios·电脑·cocoa·iphone
白玉cfc2 小时前
【iOS】内存五大分区
macos·ios·cocoa
a44931536211 小时前
iPhone 基带故障诊断——无服务/搜索不到网络的芯片级维修实录
网络·macos·ios·电脑·iphone
a44931536212 小时前
MacBook USB-C不充电故障诊断:从PD握手到主板供电链路
c语言·开发语言·macos·电脑
寒水馨13 小时前
macOS下载、安装scrcpy-v4.1(附安装包scrcpy-macos-aarch64-v4.1.tar.gz)
macos·adb·手机控制·scrcpy·投屏软件·android投屏·屏幕镜像
a44931536214 小时前
iPhone 充电故障的全链路诊断——从 Lightning/USB-C 接口到 Tristar 充电 IC
c语言·macos·ios·电脑·硬件架构·iphone
xiaowang1234shs1 天前
怪兽轻断食技术深度测评:从断食计时引擎到AI识别算法的工程实践解析
数据库·人工智能·算法·macos·机器学习·p2p·visual studio
大龄秃头程序员1 天前
揭秘 KVC 底层:Objective-C KVC 究竟依赖了哪些 Runtime 能力
objective-c
大龄秃头程序员1 天前
Objective-C 浅拷贝与深拷贝:从踩坑到彻底搞懂
objective-c