“单例模式”是我们在iOS中最常使用的设计模式之一。
单例模式不需要传递任何参数,就有效地解决了不同代码间的数据共享问题
。在应用这个模式时,单例对象的类必须保证只有一个实例存在。
在APP开发中我们可能在任何地方都要使用用户的信息,那么可以在登录的时候就把用户信息存放在一个文件里面,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。
有的情况下,某个类可能只能有一个实例。比如说你写了一个类用来播放音乐,那么不管任何时候只能有一个该类的实例来播放声音。再比如,一台计算机上可以连好几个打印机,但是这个计算机上的打印程序只能有一个,这里就可以通过单例模式来避免两个打印任务同时输出到打印机中,即在整个的打印过程中我只有一个打印程序的实例。
单例类的应用贯穿于整个iOS的SDK中。例如,UIApplication类有一个方法叫sharedApplication,从任何地方调用这个方法,都将返回与当前正在运行的应用程序相关联的UIApplication实例。除了这个,NSNotificationCenter(消息中心) 、NSFileManager(文件管理) 、 NSUserDefaults(持久化存储数据) 、NSURLCache(请求缓存)、NSHTTPCookieStorage(应用程序cookies池)都是系统单例;
单例类保证了应用程序的生命周期中有且仅有一个该类的实例对象,而且易于外界访问。
实现单例的做法有两种
第一种是 GCD的方式
第二种是线程锁synchronized
我主要是使用GCD的方式, 代码如下 :
// 声明为 id 类型 这样其他的使用者 只需要把下面的代码复制过去就能使用,不用任何修改
static id _instance= nil ;
// 保证了在对该类的实例发送 alloc init 和 new 消息的时候 拿到的会是单例
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
if (_instance == nil)
{
static dispatch_once_t onceToken ;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone] ;
}) ;
}
return _instance ;
}
+(instancetype)sharedInstance
{
if (_instance == nil)
{
static dispatch_once_t onceToken ;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] init] ;
}) ;
}
return _instance ;
}
// 保证了在对该类的实例发送copy消息的时候 拿到的还是单例
- (id)copy
{
return _instance ;
}
// 保证了在对该类的实例发送mutableCopy消息的时候 拿到的还是单例
- (id)mutableCopy
{
return _instance ;
}
可以通过shareInstanced的方式获得单例,但是会有两个潜在的问题。
第一如果developer 使用 alloc init 或者new的方式连续创建多个对象是没有单例的效果的。
第二如果developer 向实例发送copy、 mutableCopy消息 ,新的实例和原来的实例也是两个对象。所以还需要把这些方法也改成单例,确保没有后顾之忧。上面的代码已经实现了。
这里随便也贴上 synchronized的方式创建单例的办法,这种方式主要是采用线程锁的技术,在多线程同时访问一个方法的时候,只让其中一个线程执行synchronized内部。当这个线程执行完成之后其他线程再进去访问的时候_instance已经不等于nil了。(也可以在synchronized外部再加上一个_instance的非空判断来提高执行效率? 我的猜测)
static id _instance ; +(instancetype)allocWithZone:(struct _NSZone *)zone { @synchronized (self) // 保证在多线程访问的时候 有且仅有 一个线程能够执行synchronized内部 { if (_instance == nil) { _instance = [super allocWithZone:zone] ; } } return _instance ; }
+(instancetype)sharedInstance { @synchronized (self) { if (nil == _instance) { _instance = [[self alloc] init] ; } } return _instance ; }
-(id)copy { return _instance ; }
-(id)mutableCopy { return _instance ; }
参考资料
模拟多继承
NSProxy介绍
消息转发
Demo
http://www.cocoachina.com/ios/20160613/16661.html
http://www.cnblogs.com/ygm900/p/3607143.html
http://www.jianshu.com/p/7486ebfcd93b
http://www.tuicool.com/articles/v2URVji
http://www.cnblogs.com/MasterPeng/p/5000516.html
http://www.2cto.com/kf/201412/362291.html
网友评论