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. 如果单例对象的创建需要建立在某些外部前提下,那么不适合饿汉模式
相关推荐
ifeng09184 小时前
鸿蒙应用开发常见Crash场景解析:线程安全与异常边界处理
安全·cocoa·harmonyos
醇氧4 小时前
Mac 安装 Docker Desktop
macos·docker·容器
2501_916007475 小时前
iOS 压力测试的工程化体系,构建高强度、多维度、跨工具协同的真实负载测试流程
android·ios·小程序·uni-app·cocoa·压力测试·iphone
神秘人-解说6 小时前
在Mac上安装Windows 11/10双系统(M1/M2/Intel通用)
windows·macos·mac安装双系统·mac安装虚拟机·mac安装windows
知难行难7 小时前
macOS配置Apocrita及ssh访问及获取GPU权限
运维·macos·ssh
游戏开发爱好者811 小时前
Mac 抓包软件怎么选?从 HTTPS 调试、TCP 数据流分析到多工具协同的完整抓包方案
tcp/ip·macos·ios·小程序·https·uni-app·iphone
马拉萨的春天13 小时前
iOS中广告SDK如何判断一个广告是否真实展示
macos·ios·cocoa
ajassi200013 小时前
开源 Objective-C IOS 应用开发(十九)视频的播放
ios·开源·objective-c
ajassi200014 小时前
开源 Objective-C IOS 应用开发(二十二)自定义控件--车速仪表盘
ios·开源·objective-c
ajassi200018 小时前
开源 Objective-C IOS 应用开发(二十一)自定义控件--示波器
ios·开源·objective-c