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

单例模式重新学习

文章目录

  • 从头开始构建单例
  • 饿汉模式
  • 总结
  • P.S:Code Snippets:自定义代码片段

在开发项目中,有很多时候我们需要一个全局的对象,而且要保证全局有且仅有一份即可,单例在这个时候就是最佳的选择,系统已经有很多单例存在,例如UIApplication、NSNotification、NSFileManager等等

从头开始构建单例

我们先来看一个最简单的单例模式,首先我们要有一个能够在全局获取到单例的类方法

 + (id)sharedInstance {  static Singleton *instance = nil;if (!instance) {  instance = [[super allocWithZone:NULL] init];}  return instance;  }  

但其实如果按照这个写法,在遇到多线程时,是有可能多次初始化单例

所以我们使用dispatch_once保证线程安全,dispatch_once是原子性的

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

接下来实现类本身的方法

一个自定义类,应该需要申请内存(alloc)和初始化(init)两步,

我们要确保对象的唯一性,因此在第一步这个阶段我们就要拦截它。当我们调用alloc方法时,OC内部会调用allocWithZone这个方法来申请内存,我们重写这个方法,然后在这个方法中调用shareInstance方法返回单例对象,这样就可以达到我们的目的

除了申请内存和初始化,拷贝也有可能会导致单例出现多次,所以重写copyWithZone方法,然后在这个方法中调用shareInstance方法返回单例对象

+ (instancetype)sharedInstance {static Singleton *instance = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{instance = [[super allocWithZone:NULL] init];});return instance;
}+ (instancetype)allocWithZone:(struct _NSZone *)zone {return [self sharedInstance];
}- (id)copyWithZone:(NSZone *)zone {return self;
}- (id)mutableCopyWithZone:(NSZone *)zone {return self;
}

这样,一个基本的单例方法,就全部实现了,基本上可以避免出现多个实例或者奇奇怪怪的情况出现

这种方式叫做懒汉模式,这种模式创建出的单例只会在我们需要的时候创建,这种模式可以节省系统资源,提高性能

饿汉模式

饿汉模式与懒汉模式最大的不同就是他们会在一开始就把示例创建好,一般来说,会在load中创建示例来实现

+load 方法是当类或者分类被加载到内存中时,系统自动调用的,该方法只会调用一次,所有的类都会在程序启动的时候加载一次

// 在类的实现文件中声明一个静态实例
static Singleton *instance = nil;@implementation Singleton// 在 +load 方法中创建单例实例
+ (void)load {instance = [[super allocWithZone:NULL] init];
}// 饿汉模式的全局访问点
+ (instancetype)sharedInstance {return instance;
}// 重写 allocWithZone: 方法,确保无法通过 alloc 直接创建新实例
+ (instancetype)allocWithZone:(struct _NSZone *)zone {// 直接返回已经创建好的单例实例return [self sharedInstance];
}// 重写 copy 和 mutableCopy 方法,防止实例被复制
- (id)copyWithZone:(NSZone *)zone {return self;
}- (id)mutableCopyWithZone:(NSZone *)zone {return self;
}@end

由于load方法只会调用一次,并且是系统调用,所以这里绝对是线程安全的,我们也就不需要加入dispatch_once 来保证线程安全的问题了

总结

  • 饿汉模式
    • 创建时机:应用启动时
    • 优点:简单、线程安全、调用快
    • 适用场景:单例对象不大,或者在应用生命周期中几乎总是会用到
  • 懒汉模式
    • 创建时机:第一次使用时
    • 优点:节省内存、减少启动耗时
    • 适用场景:单例对象比较大,或者不确定是否会用到

在 iOS 开发中,懒汉模式(尤其是使用 dispatch_once 的方式)是最常用和推荐的单例实现方式。它结合了懒加载的优点,同时完美地解决了线程安全问题,是目前最优雅的解决方案

P.S:Code Snippets:自定义代码片段

Code Snippets是一个可以帮助你减少写重复代码的工具

对于单例这种可能会经常用的代码块,可以添加入自定义的代码片段

我们只需要:

  1. 选中代码
  2. 右键 → Create Code Snippet
  3. 设置快捷键,比如 singleton

以后输入singleton 就可以立即展开代码片段

在这里插入图片描述

之后的重复代码也都可以通过这个方式来添加进xcode


文章转载自:

http://wl37ca5Y.jzykq.cn
http://dn0uricC.jzykq.cn
http://D9a4LhRD.jzykq.cn
http://iWEUwQcN.jzykq.cn
http://rh3wXgi6.jzykq.cn
http://TYrD1qGw.jzykq.cn
http://4oaraeyC.jzykq.cn
http://DYja75XB.jzykq.cn
http://h83C4FLy.jzykq.cn
http://p6QIzxG8.jzykq.cn
http://sCcPuf37.jzykq.cn
http://iYex7QGt.jzykq.cn
http://WpApoSGK.jzykq.cn
http://E7vzIdmc.jzykq.cn
http://J35BmnpQ.jzykq.cn
http://nIb1Gwx2.jzykq.cn
http://Kk5E2QAb.jzykq.cn
http://6RMl5ROX.jzykq.cn
http://4EetGqMW.jzykq.cn
http://a19nEyu2.jzykq.cn
http://Jg4odZwQ.jzykq.cn
http://22nBtr5F.jzykq.cn
http://c9bsEelB.jzykq.cn
http://Z37aThzc.jzykq.cn
http://vUdsLaAX.jzykq.cn
http://boIxZn14.jzykq.cn
http://Kzd9Ubg9.jzykq.cn
http://CyaXEvTI.jzykq.cn
http://nC0TNwL9.jzykq.cn
http://pMNWSlxY.jzykq.cn
http://www.dtcms.com/a/383463.html

相关文章:

  • 【系列文章】Linux中的并发与竞争[04]-信号量
  • Linux入门(二)
  • Transformer 面试题及详细答案120道(41-50)-- 训练与优化
  • UDP-Server(3)chat聊天室
  • 【不背八股】12.十大排序算法
  • 华清远见25072班网络编程学习day5
  • 【CMake】List
  • Linux系统中查找某个动态库例如.so文件是哪个软件安装的
  • c++ unqiue指针
  • ​Go语言实战案例 — 工具开发篇:编写一个进程监控工具​
  • Roo Code 的检查点功能
  • 【go/gopls/mcp】官方gopls内置mcp server使用
  • 【无标题】神经网络算法初探
  • Genspark AI 浏览器
  • Linux内核IPsec接收机制剖析:XFRM框架与xfrm4_input.c的深度解读
  • Linux 系统下的流量控制工具之tc命令案例解析
  • 数据库造神计划第五天---增删改查(CRUD)(1)
  • 深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)第九章知识点问答(10题)
  • AI表征了西方的有界,AI+体现了东方的无界
  • 前端基础 —— B / CSS基础
  • Qwen2.5-VL 实战:用 VLM 实现 “看图对话”,从目标检测到空间推理!【附源码】
  • vLLM - EngineCoreClient
  • MySQL专题Day(2)————存储引擎
  • 多文件编程与宏的使用
  • 第5节-连接表-Inner-Join
  • 【Csp - S】 图的知识
  • 【图文详解】MCP、A2A的核心技术特点以及架构模式
  • Java基础 9.13
  • Shell 正则表达式完全指南
  • 玩转ClaudeCode:用Database-MCP实现自然语言操作数据库