原创Blog,转载请注明出处
http://blog.csdn.net/hello_hwc?viewmode=list
我的stackoverflow
感谢
感谢《Pro Objective-C Design Pattern for iOS》一书,这个博客系列由很多灵感源自次书。同时,也感谢Wiki以及一些博客博主。每篇文章最后,都会列出参考链接。
设计模式是为了解决一类问题而出现的,要深刻理解某个模式的应用场景,优点,缺点。千万不要为了使用而实用,那样很可能写出不伦不类的东西。
对于同一种模式,每个人的理解都不同,能解决实际问题才是关键,所以,一定要搞清楚每种设计模式究竟解决了那一类问题,对于设计模式,可以首先理解设计出的接口,再理接口内部的实现
什么是单例模式?
保证类只有一个实例,并且提供一个访问它的全局访问点
//客户端代码
let instance = Singletonlass.sharedInstance()
在C++中,可以让构造函数为private,隐藏对应接口,但是在iOS开发中不需要,也很难做到。
在Cocoa中,单例模式的使用是十分广泛的,例如UIApplication,NSFileManager.包括一些知名的开源库,AFNetworking,SDWebImage,MagicRecord在架构的时候,也使用了单例。单例使得在使用类的时候不需要强引用一个对象。
解决什么问题?
- 类只能有一个实例,例如一个App只能有一个UIApplication实例
- 唯一的实例只能通过继承来扩展,并且扩展后客户端的代码不需要任何修改
什么时候使用单例?
- 类只能有一个实例,例如一个App只能有一个UIApplication实例
- 通常单例的生命周期和App的生命周期相同,单例作为全局的访问点
不要滥用单例模式
关于单例模式的使用,objc.io的这篇文章讲的很好,摘取一些观点
- 单例是一种全局状态,意味着App的任何地方都可以和这个单例进行交互,无形中增加了代码的耦合行
- 单例的生命周期难以控制,虽然可以在单例中提供方法设为nil进行释放。
举个例子吧,
在我的App中,要设计一个类来统计用户的行为(这里不用友盟等第三方统计平台是因为不方便),这个类的主要任务有以下几点:
- 在Sandbox中建立一个Log目录,把用户行为Log到本地;
- 维护内存中的Log缓冲区(虽然Log相关的操作都在后台,但是还是不想频繁的于物理存储交互);
- 同服务器进行同步,同时根据同步的结果清理文件;
- 在必要的时候,能根据后台返回数据禁止Log;
那么,如何设计这个类呢?
这个类的特点:App中许多控件 or Controller都需要同它进行交互;这个类不管现在还是以后,都可以和App生命周期一致。
所以,这个类使用了单例。同时,提供类函数这样的接口(暂时没讲到接口相关的设计模式)。
Objective C中的单例
+ (instancetype)sharedSingleton {
static Singleton *_sharedSingleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedSingleton = [[Singleton alloc] init];
});
return _sharedSingleton;
}
Swift的单例
注意,在Swift中由let声明的类常量支持惰性初始化(lazy),并且是线程安全的
class SingletonA {
static let sharedInstance = SingletonA()
//Other
}
当然,也可以像Objective C中那么写
class Singleton {
class var sharedInstance: Singleton {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: Singleton? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = Singleton()
}
return Static.instance!
}
}
参考链接
- WIKI Singleton Pattern
- objc.io避免滥用单例
- StackOverflow-When to use Singleton in iOS