持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
- 本文主要介绍iOS设计模式中
单例模式的介绍,单例模式是我们平时使用比较多的一种设计模式,提供了对类的对象所提供的资源的全局的访问点,因此我们可以使用单例返回的对象进行传递值等。
1. 什么是单例模式
单例模式是设计模式的最简单的形式了。这一模式的意图是使得类的一个对象成为系统中的唯一实例。我们通常会使用类方法返回实例对象,因此我们可以使用工厂方法进行实现改类在程序中只实例化一次。该方法我们首先判读是否存在实例,不存在的话进行实例之后返回该实例。
在数学中。singleton指“单元素集合”,指仅由一个元素组合成的集合。
单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
2. 什么时候使用单例模式
- 类
只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法。 - 这个唯一的实例只能
通过子类化进行拓展,而且拓展的对象不会破坏客户端代码。单例模式提供了一个为人熟知的访问点,提供客户类为共享资源生成唯一实例,并通过它对共享资源进行访问,虽然静态的全局对象引用或类方法也可以提供全局访问点,但是全局对象无法防止类被实例化一次以上,而且类方法也缺少消除耦合的灵活性。
比如我们APP中保存用户的信息类,UserModel的信息在全局中多次被用到,同时我们只要一次实例化,这个时候使用单例模式就可以提供了灵活性。或者是网络请求的工具类我们实例化一次,全局都可以使用。
3. 在Cocoa Touch中使用单例模式
我们在开发中会发现大量的单列类,这里简单的介绍下UIApplication和NSFileManager。
3.1 UIApplication
每个iOS应用程序都恰好有一个UIApplication实例(或很少是UIApplication的子类)。当应用程序启动时,系统调用UIApplicationMain(_:_:_:_:)函数。除其他任务外,此函数创建一个单例UIApplication对象,您可以使用shared访问。
UIApplication对象为应用程序处理许多内务管理任务,包括传入的用户事件的最初路由,以及为UIController分发动作消息给合适的目标。并且还维护应用程序中打开所有UIWindow对象的列表。应用程序对象总是被分配给一个UIApplicationDelegate对象,把运行时事件通知给她。
3.2 NSFileManager
文件管理器对象允许您检查文件系统的内容并对其进行更改。NSFile类提供了对共享文件管理器对象的便捷访问,该对象适用于大多数类型的文件相关操作。文件管理器对象通常是您与文件系统交互的主要模式。您使用它来定位、创建、复制和移动文件和目录。您还可以使用它来获取有关文件或目录的信息或更改其某些属性。
可以通过defaultManager进行访问,但是可能会存在线程安全问题。
可以从多个线程安全地调用共享NSFile对象的方法。但是,如果您使用委托接收有关移动、复制、删除和链接操作状态的通知,您应该创建文件管理器对象的唯一实例,将委托分配给该对象,并使用该文件管理器启动操作。
4. 代码展示
单利通常有2种写法,第一种:
static Network *_network;
+(instancetype)share
{
if (!_network) {
_network = [[Network alloc]init];
}
return _network;
}
这样写会在多线程情况下导致重复创建,不安全。通常会添加一个同步锁
+(instancetype)share
{
@synchronized (self) {
if (!_network) {
_network = [[Network alloc]init];
}
}
return _network;
}
继续优化下,防止每次读取造成卡顿,外面在加一层判断。
+(instancetype)share
{
if (!_network) {
@synchronized (self) {
if (!_network) {
_network = [[Network alloc]init];
}
}
}
return _network;
}
第二种:看下GCD单例写法
static Network *_network;
+(instancetype)shareInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_network = [[Network alloc]init];
});
return _network;
}
当然为了防止alloc和copy导致实例化我们通常也会实现allocWithzone和copyWithZone,用来确定唯一性。
5. 总结
单例模式在我开发生涯中,使用的比较多,但是大量的单例模式使用会造成内存长期处于无法释放的状态,虽然解决了我们传值,状态保存等方便性。但是它违返了单一职责原则。单例模式可能掩盖不良设计, 比如程序各组件之间相互了解过多等。