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

【iOS】单例模式

【iOS】单例模式

  • 前言
  • 定义
  • 优缺点
    • 优点
    • 缺点
  • 种类
    • 懒汉式
    • 饿汉式
    • 优缺点比较
  • 总结

前言

单例模式是很重要的一部分内容,这里重点总结复习一下。

定义

单例模式是一种设计模式,保证一个类在程序运行中只会有一个实例,并且提供全局访问点。这样防止一个实例被重复创建而占用内存空间,大大节省了内存。

优缺点

优点

  • 一个类只被实例化了一次,提供了对唯一实例的受控访问
    • 保证所有人拿到的是同一个对象
    • 保证在需要时才初始化,也就是之前博客中提到的懒加载
Person *p1 = [[Person alloc] init];
Person *p2 = [[Person alloc] init];
NSLog(@"%p %p", p1, p2);
//每次alloc init,会输出不同地址
MyManager *m1 = [MyManager sharedManager];
MyManager *m2 = [MyManager sharedManager];
NSLog(@"%p %p", m1, m2); 
//避免重复创建,输出的是相同地址
  • 节省系统资源

缺点

  • 全局状态:单例模式可能导致全局状态存在,就是程序不同模块都可能修改这个单例对象的状态,增加代码复杂性,且bug不好定位。
  • 难以扩展:单例模式的实例是固定的,导致很难扩展以支持多个实例。
  • 不适用于多线程环境:在多线程环境下,需要处理保证初始化代码只执行一次,而且线程是安全的。
    • 互斥锁:
    + (instancetype)sharedInstance {@synchronized (self) {if (_instance == nil) {_instance = [[self alloc] init];}}return _instance;
    }
    
    • dispatch_once
    + (instancetype)sharedInstance {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{_instance = [[self alloc] init];});return _instance;
    }
    

种类

懒汉式

主要指在需要时才会创建单例对象的实例,而不是在程序启动时就立即创建(懒加载)。懒汉式通过延迟对象的初始化来节省资源和提高性能。

这里展示两种写法:

  • 双重检查锁
#import "ViewController.h"@interface ViewController ()@end@implementation ViewControllerstatic id _instance;+(instancetype)allocWithZone:(struct _NSZone *)zone {if (_instance == nil) {@synchronized (self) {if (_instance == nil) {_instance = [super allocWithZone:zone];}}}return _instance;
}+(instancetype)shareSingleton {if (_instance == nil) {@synchronized (self) {if (_instance == nil) {_instance = [[self alloc] init];}}}return _instance;
}- (void)viewDidLoad {[super viewDidLoad];_instance = [[NSString alloc] init];_instance = @"单例模式";NSLog(@"%@", _instance);
}-(id)copyWithZone:(NSZone *)zone {return _instance;
}-(id)mutableCopyWithZone:(NSZone *)zone {return _instance;
}@end

这里详细解释一下这种写法中几个重要的需要注意的点:

  1. static id _instance:static用于保存类的唯一实例,保证进程中只有一份,更具体的将在单独写篇博客来比较static、const、extern关键字。
  2. 重写allocWithZone::双重检查锁来保证线程安全,当外部调用alloc init时,保证始终只分配一次内存。
  3. copyWithZone:mutableCopyWithZone::用于复制对象的方法,它们都被重写后返回同一个_instance,保证不会生成新对象,仍然符合单例模式的要求。
  • GCD写法
#import "sharedSingleton.h"static id _instance = nil;@implementation sharedSingleton+(instancetype)sharedSingleton {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{_instance = [[super allocWithZone:NULL] init];});return _instance;
}+(instancetype)allocWithZone:(struct _NSZone *)zone {return [sharedSingleton sharedSingleton];;
}-(id)copyWithZone:(NSZone *)zone {return [sharedSingleton sharedSingleton];
}-(id)mutableCopyWithZone:(NSZone *)zone {return [sharedSingleton sharedSingleton];
}@end

dispatch_once主要是根据onceToken的值来决定怎么去执行代码:

  1. 当onceToken = 0时,线程执行block中的代码
  2. 当onceToken = -1时,线程跳过block中的代码不执行
  3. 当onceToken = 其他值时,线程被阻塞,等待onceToken值改变

饿汉式

饿汉式创建单例是在你的类加载时立即开始加载一个单例的一种单例模式,这种模式需要我们把加载单例的代码写在类第一次加载的位置。

#import "ehanSingleton.h"static id _instance;@implementation ehanSingleton//当类加载到OC运行时的环境内存中调用
+(void)load {_instance = [[self alloc] init];
}+(instancetype)ehanSingleton {return _instance;
}+(instancetype)allocWithZone:(struct _NSZone *)zone {if (!_instance) {_instance = [super allocWithZone:zone];}return _instance;
}-(id)copyWithZone:(NSZone *)zone {return _instance;
}-(id)mutableCopyWithZone:(NSZone *)zone {return _instance;
}@end

优缺点比较

  • 懒汉式:
    • 优点:
      • 懒加载:只有在第一次访问单例实例的时候才会被创建,这样可以节省资源,提高性能。
      • 线程安全:通过GCD或加锁来保证线程安全性。
      • 节省内存:如果单例对象很大或者初始化过程开销较大,懒汉模式可避免在程序启动时就创建不必要的对象。
    • 缺点:
      • 线程安全性的开销:为保证线程安全的操作带来性能上的开销。
  • 饿汉式:
    • 优点:
      • 创建方式简单:不出现多线程的问题。
      • 线程安全:实例在类创建时就创建,不会存在多个实例的风险,保证线程安全。
    • 缺点:
      • 性能问题:如果单例类的实例在启动程序时没有被使用,那么创建实例的开销可能是不必要的。
      • 无法实现延迟加载:饿汉模式在程序启动时就创建实例,无法实现延迟加载,可能会浪费资源,尤其是当实例很大或初始化开销较大时。

总结

总的来说,懒汉模式适用于需要延迟加载实例的情况,饿汉模式适用于需要简单实现和线程安全性的情况,具体情况具体分析。


文章转载自:

http://BmnhqYqL.mkyny.cn
http://ZTsB1hi9.mkyny.cn
http://3lt6Q5Dp.mkyny.cn
http://KLZHTPfd.mkyny.cn
http://y6cDNOwe.mkyny.cn
http://kdriPMBn.mkyny.cn
http://evvMlw26.mkyny.cn
http://xpqUH2rm.mkyny.cn
http://M9aENnSy.mkyny.cn
http://mwzqGfdl.mkyny.cn
http://xYDnKj2K.mkyny.cn
http://yeVjUbVq.mkyny.cn
http://L6g6sWTD.mkyny.cn
http://1H7TjA3V.mkyny.cn
http://1CLw1Ubc.mkyny.cn
http://5UMOhqHL.mkyny.cn
http://0bWt6Hyg.mkyny.cn
http://ctZNmjTL.mkyny.cn
http://xkzqvKcy.mkyny.cn
http://783fiRcR.mkyny.cn
http://Q7dtYgKR.mkyny.cn
http://J4tdMtnf.mkyny.cn
http://j9wjXHab.mkyny.cn
http://huwdXmWg.mkyny.cn
http://JQXAeDqB.mkyny.cn
http://QsClt7B7.mkyny.cn
http://pfxUJQVd.mkyny.cn
http://DAkPiU9M.mkyny.cn
http://xc691jc9.mkyny.cn
http://NlXf9PoV.mkyny.cn
http://www.dtcms.com/a/376340.html

相关文章:

  • 工业智能终端赋能自动化生产线建设数字化管理
  • 在Vue项目中Axios发起请求时的小知识
  • eclipse怎么把项目设为web
  • 三维GIS开发实战!Cesium + CZML 实现火箭飞行与分离的 3D 动态模拟
  • Hybrid应用性能优化实战分享(本文iOS 与 H5为例,安卓同理)
  • Python 常用数据类型详解:相同点、差异与使用指南
  • Elasticsearch安装启动常见问题全解析
  • webpack turbopack vite 前端打包工具
  • NLP项目实战 | Word2Vec对比Glove进行词类比测试
  • 基于密集型复杂城市场景下求解无人机三维路径规划的Q-learning算法研究(matlab)
  • 南京大学 LLM开发基础(一)前向反向传播搭建
  • GitHub 热榜项目 - 日榜(2025-09-10)
  • 基于YOLO集成模型的无人机多光谱风电部件缺陷检测
  • ssh域名过期,消息推送到企业微信
  • 【Python】爬虫html提取内容基础,bs4
  • zabbix告警推送钉钉
  • Android系统框架知识系列(二十):专题延伸:JVM vs ART/Dalvik - Android运行时演进深度解析
  • 关于在pycharm终端连接服务器
  • VPS、云服务器、独立服务器的区别是什么?新手服务器选择指南
  • 10. 游戏开发中的TCP与UDP
  • 第1章:操作系统和计算机网络
  • 在uniapp/vue项目中全局挂载component
  • 【ubuntu 24.04 LTS】真实实验部署ollama0.11.6+deepseekR1:1.5b+open-webUI
  • [万字长文]AJAX入门-常用请求方法和数据提交、HTTP协议-报文、接口文档、案例实战
  • 基于 Vue3 + VueOffice 的多格式文档预览组件实现(支持 PDF/Word/Excel/PPT)
  • 【Unity UGUI 交互组件——Scrollbar(8)】
  • 报错Failed to set ntp: NTP not supported
  • 零基础学AI大模型之读懂AI大模型
  • 《嵌入式硬件(六):ARM汇编核心内容总结》
  • 力扣刷题笔记-三数之和