Swift、Objective-C 单例模式 (Singleton)
Swift、Objective-C 单例模式 (Singleton)
本文的单例模式分为严格单例模式和不严格单例模式。单例模式要求一个类有一个实例,有公开接口可以访问这个实例。严格单例模式,要求一个类只有一个实例;不严格单例模式,可以创建多个实例。
有的类只能有一个实例,例如 UIApplication,通过 shared 属性访问唯一的实例,属于严格单例模式。有用户登录功能的 App 中,如果当前用户的数据模型与其他用户的数据模型不同,那么当前用户的类也应该用严格单例模式。在逻辑上,当前用户只有一个,只能有一个实例;这样可以在各个地方访问当前用户的数据。如果当前用户的数据模型与其他用户的数据模型相同,则应用不严格单例模式。可以给其他用户创建实例,同时也可以在各个地方访问当前用户的数据。
Swift 实现
严格单例模式
大多数 Objective-C 的类都继承自 NSObject,而 Swift 的类可以继承自 NSObject 或者不继承。
继承自 NSObject
class SingletonClass: NSObject {
static let shared = SingletonClass()
// Make sure the class has only one instance
// Should not init or copy outside
private override init() {}
override func copy() -> Any {
return self // SingletonClass.shared
}
override func mutableCopy() -> Any {
return self // SingletonClass.shared
}
// Optional
func reset() {
// Reset all properties to default value
}
}
静态属性 shared 持有唯一的实例,对外公开。
重载 init() 方法,使其对外不可见,不可以在外部调用,防止在外部创建实例。
重载 copy()、mutableCopy() 方法,返回 self,防止在外部复制实例。这里也可以返回 SingletonClass.shared,效果是一样的,因为只有一个实例。只有 shared 能调用 copy()、mutableCopy() 方法,那么 self 就是 shared。写 self,代码比较简洁。
单例一旦创建,一直持有,不能手动销毁,但可以重置数据。如果需要的话,可以添加一个重置数据的方法 reset()。例如,当前用户退出登录,需要把当前用户实例的所有属性重置为默认值,防止数据错误。
不继承自 NSObject
class SingletonClass2 {
static let shared = SingletonClass2()
// Make sure the class has only one instance
// Should not init outside
private init() {}
// Optional
func reset() {
// Reset all properties to default value
}
}
不继承自 NSObject 的类没有 copy()、mutableCopy() 方法,不需要重载。其他同上。
不严格单例模式
把重载的 init() 方法去掉,或者把 private 去掉,即可创建多个实例。如果继承自 NSObject,重载 copy()、mutableCopy() 方法:创建新实例,传递数据给新实例,返回新实例。其他与严格单例模式相同。
不严谨的重置数据方法
如果单例有很多属性,重置数据需要把每个属性都变成默认值,则 reset() 方法要写很多。有一种不严谨的重置数据方法:重新生成一个实例并赋值给持有实例的静态变量。
class SingletonClass3 {
private static var _shared = SingletonClass3()
static var shared: SingletonClass3 {
return _shared
}
private init() {}
// Not safe
// We can obtain more than one instance outside with this function
func reset() {
SingletonClass3._shared = SingletonClass3()
}
}
如果在外部访问单例都通过 shared 属性,这么写不会出错。然而,如果外部持有单例,就有可能出错。
let s = SingletonClass3.shared
s.reset()
print(s === SingletonClass3.shared) // false
以上会输出 false,s 在重置之后,和 SingletonClass3.shared 不是同一个对象。因此,这样的重置数据方法不严谨。还是要老老实实把每个属性赋为默认值。
Objective-C 实现
严格单例模式
.h 文件
@interface SingletonClassOC : NSObject
+ (nonnull instancetype)shared;
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
- (id)copy NS_UNAVAILABLE;
- (id)mutableCopy NS_UNAVAILABLE;
@end
.m 文件
@implementation SingletonClassOC
+ (nonnull instancetype)shared {
static id _shared;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_shared = [[self alloc] init];
});
return _shared;
}
// Optional
- (void)reset {
// Reset all properties to default value
}
@end
在 .h 文件中,用 NS_UNAVAILABLE 禁用初始化和拷贝方法,只允许用过 shared 方法访问唯一实例。
静态变量 _shared 持有唯一的实例,通过 shared 方法对外公开。由 dispatch_once 保证 _shared 只初始化一次。方法返回值的 nonnull 表示返回值不为空,这样写方便 Swift 调用。不加 nonnull,shared 方法在 Swift 中的返回值是 optional 类型 (SingletonClassOC?),不方便使用;加上 nonnull 则为 SingletonClassOC 类型。
如果需要,用 reset 方法重置数据。
不严格单例模式
.h 文件
@interface SingletonClassOC2 : NSObject
+ (nonnull instancetype)shared;
@end
.m 文件
@implementation SingletonClassOC2
+ (nonnull instancetype)shared {
static id _shared;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_shared = [[self alloc] init];
});
return _shared;
}
- (id)copyWithZone:(NSZone *)zone {
SingletonClassOC2 *copiedObject = [[self.class allocWithZone:zone] init];
// Copy data to copiedObject
return copiedObject;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
SingletonClassOC2 *copiedObject = [[self.class allocWithZone:zone] init];
// Copy data to copiedObject
return copiedObject;
}
- (void)reset {
// Reset all properties to default value
}
@end
公开的 shared 方法与严格单例模式相同。外部可以通过 init 方法创建与 _shared 不同的实例。
重载 copyWithZone: 和 mutableCopyWithZone: 方法,在里面创建新实例,传递数据给新实例,返回新实例。外部可以通过 copy 或 mutableCopy 方法复制实例。
SDWebImage 中就用到不严格单例模式
NSObject 的类方法 new 相当于 alloc 和 init 方法。
转载请注明出处:http://www.cnblogs.com/silence-cnblogs/p/6776217.html
Swift、Objective-C 单例模式 (Singleton)的更多相关文章
- 设计模式之单例模式——Singleton
设计模式之单例模式--Singleton 设计意图: 保证类仅有一个实例,并且可以供应用程序全局使用.为了保证这一点,就需要这个类自己创建自己的对象,并且对外有 ...
- 【白话设计模式四】单例模式(Singleton)
转自:https://my.oschina.net/xianggao/blog/616385 0 系列目录 白话设计模式 工厂模式 单例模式 [白话设计模式一]简单工厂模式(Simple Factor ...
- ooad单例模式-Singleton
单例模式Singleton 主要作用是保证在Java应用程序中,一个类Class只有一个实例存在. 比如建立目录 ...
- iOS单例模式(Singleton)写法简析
单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 1.单例模式的要点: 显然单例模式的要点有三个:一是某个类只能有一个实例: ...
- 浅谈设计模式--单例模式(Singleton Pattern)
题外话:好久没写blog,做知识归纳整理了.本来设计模式就是个坑,各种文章也写烂了.不过,不是自己写的东西,缺少点知识的存在感.目前还没做到光看即能记住,得写.所以准备跳入设计模式这个大坑. 开篇先贡 ...
- 设计模式之——单例模式(Singleton)的常见应用场景
单例模式(Singleton)也叫单态模式,是设计模式中最为简单的一种模式,甚至有些模式大师都不称其为模式,称其为一种实现技巧,因为设计模式讲究对象之间的关系的抽象,而单例模式只有自己一个对象,也因此 ...
- 设计模式之单例模式(Singleton Pattern)
单例模式 单例模式(Singleton Pattern)在java中算是最常用的设计模式之一,主要用于控制控制类实例的数量,防止外部实例化或者修改.单例模式在某些场景下可以提高系统运行效率.实现中的主 ...
- 设计模式(4) -- 单例模式(Singleton)
设计模式(4) -- 单例模式(Singleton) 试想一个读取配置文件的需求,创建完读取类后通过New一个类的实例来读取配置文件的内容,在系统运行期间,系统中会存在很多个该类的实例对象,也就是说 ...
- IOS单例模式(Singleton)
IOS单例模式(Singleton) 单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 1.单例模式的要点: 显然单例模 ...
随机推荐
- MD5加密 32位
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; ...
- “Dynamic Web Module 3.0 requires Java 1.6 or newer.”错误 (转别人)
eclipse maven 在项目的pom.xml的<build></build>标签中加入: <plugins> <plugin> <group ...
- 二、Fragment+RadioButton实现底部导航栏
在App中经常看到这样的tab底部导航栏 那么这种效果是如何实现,实现的方式有很多种,最常见的就是使用Fragment+RadioButton去实现.下面我们来写一个例子 首先我们先在activi ...
- 分享几个不错的Android开源音视频播放器
整理了一下Github上几个开源的音视频播放器项目,有兴趣的同学可以clone代码去研究学习. UniversalMusicPlayer https://github.com/googlesamp ...
- WPF+AE开发小结--TOCControl右键菜单删除图层
1.WPF项目中添加toccontrol控件,如何添加,网上有很多方法,可自行搜索,这里不再赘述,代码如下 <Window x:Class="AE.MainWindow" x ...
- .net core版 文件上传/ 支持批量上传,拖拽以及预览,bootstrap fileinput上传文件
asp.net mvc请移步 mvc文件上传支持批量上传,拖拽以及预览,文件内容校验 本篇内容主要解决.net core中文件上传的问题 开发环境:ubuntu+vscode 1.导入所需要的包:n ...
- es6中的let声明变量与es5中的var声明变量的区别,局部变量与全局变量
自己通过看typescript官方文档里的let声明,与阮一峰老师翻译的的es6学习文档,总结以下三点 1.var声明可以多次重复声明同一个变量,let不行 2.let变量只在块级作用域里面有效果,v ...
- Vue.js 学习笔记 一
本文的Demo和源代码已放到GitHub,如果您觉得本篇内容不错,请点个赞,或在GitHub上加个星星! https://github.com/zwl-jasmine95/Vue_test 以下所有知 ...
- Java面试题:写代码使得分别出现StackOverflowError和OutOfMemoryError
转载自:http://www.cnblogs.com/xudong-bupt/p/3360206.html 今天做了个笔试,这是其中的一道题目:写代码使得分别出现StackOverflowError和 ...
- c/c++程序员的技术栈
在当今的互联网时代, java, 安卓, ios, 大行其道,而c/c++却显得越来越落寞. 其实这并不是c/c++程序员本身的问题,而是这是一个产品快速响应市场的年代.用过c/c++的人都知道, ...