当前位置: 首页 > news >正文

OC-单例模式

文章目录

  • 单例模式
    • 定义
    • 特点
    • 使用原因
    • 缺点
    • 模式介绍
      • 懒汉模式
        • 同步锁实现
        • dispatch_once
      • 饿汉模式
        • 实现
    • 总结
      • 懒汉模式
        • 优点
        • 缺点
      • 饿汉模式
        • 优点
        • 缺点

单例模式

定义

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

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

特点

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

使用原因

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

缺点

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

模式介绍

懒汉模式

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

同步锁实现
#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已经存在是没有必要进入锁的,所以可以再加个判断如下:

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

#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

我们打印出不同情况下的对象地址如下:
请添加图片描述

饿汉模式

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

实现
#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. 如果单例对象的创建需要建立在某些外部前提下,那么不适合饿汉模式

文章转载自:

http://UqTJWsUl.dxqfh.cn
http://kBcVJt0U.dxqfh.cn
http://dUSwD3p4.dxqfh.cn
http://MQvUOH7l.dxqfh.cn
http://QuLQTGKq.dxqfh.cn
http://x3CkXRFW.dxqfh.cn
http://kYxz55ZF.dxqfh.cn
http://ONjMCJA8.dxqfh.cn
http://tsOh94e2.dxqfh.cn
http://D3zCtlNb.dxqfh.cn
http://o56Y4HDU.dxqfh.cn
http://kmiQRXUH.dxqfh.cn
http://AenXdzV5.dxqfh.cn
http://I5faPosQ.dxqfh.cn
http://1EFKDSvu.dxqfh.cn
http://BdBx3ZaW.dxqfh.cn
http://47KxClmz.dxqfh.cn
http://igFd1wcc.dxqfh.cn
http://oe1HIbVZ.dxqfh.cn
http://LcGZIfFI.dxqfh.cn
http://5H7sFDKH.dxqfh.cn
http://kifDAY3J.dxqfh.cn
http://3kMI0ZuH.dxqfh.cn
http://fTtpaODh.dxqfh.cn
http://eqvhGDAK.dxqfh.cn
http://tb58Sgeo.dxqfh.cn
http://JF8LnbEb.dxqfh.cn
http://iTm9y007.dxqfh.cn
http://qN1EcEVR.dxqfh.cn
http://SIcwvrtT.dxqfh.cn
http://www.dtcms.com/a/374558.html

相关文章:

  • C语言链表设计及应用
  • 中级统计师-统计法规-第三章 统计法的基本原则
  • 【VR音游】音符轨道系统开发实录与原理解析(OpenXR手势交互)
  • web前端安全-什么是供应链攻击?
  • Saucony索康尼推出全新 WOOOLLY 运动生活羊毛系列 生动无理由,从专业跑步延展运动生活的每一刻
  • 后端(FastAPI)学习笔记(CLASS 2):FastAPI框架
  • Java如何实现一个安全的登录功能?
  • AI中的“预训练”是什么意思
  • 量子文件传输系统:简单高效的文件分享解决方案
  • 基于Springboot + vue实现的乡村生活垃圾治理问题中运输地图
  • 分布式专题——5 大厂Redis高并发缓存架构实战与性能优化
  • 下载 Eclipse Temurin 的 OpenJDK 提示 “无法访问此网站 github.com 的响应时间过长”
  • 从嵌入式状态管理到云原生架构:Apache Flink 的演进与下一代增量计算范式
  • Gradio全解11——Streaming:流式传输的视频应用(2)——Twilio:网络服务提供商
  • 服务器更换jar包,重启后端服务
  • 人形机器人赛道的隐形胜负手:低延迟视频链路如何决定机器人未来
  • 分钟级长视频生成迎来“记忆革命”,7倍成本降低,2.2倍端到端生成速度提升!|斯坦福字节
  • 多张图片生成视频模型技术深度解析
  • electron安装失败
  • Electron+Vite+Vue项目中,如何监听Electron的修改实现和Vue一样的热更新?[特殊字符]
  • IEEE出版,限时早鸟优惠!|2025年智能制造、机器人与自动化国际学术会议 (IMRA 2025)
  • Next.js vs Create React App:2025年该如何选择?
  • React From表单使用Formik和yup进行校验
  • 响应式编程思想与 Reactive Streams 规范
  • [react] react onClick函数的认知陷阱
  • Vue3 + Vite + Element Plus web转为 Electron 应用
  • 【算法】四大基础数据结构
  • ARM-汇编的基础知识
  • 【C++】19. 封装红⿊树实现set和map
  • 多目标轮廓匹配