美文网首页
Singleton && NSProxy

Singleton && NSProxy

作者: 蜗牛也有梦想 | 来源:发表于2017-02-26 16:23 被阅读8次

    “单例模式”是我们在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

    相关文章

      网友评论

          本文标题:Singleton && NSProxy

          本文链接:https://www.haomeiwen.com/subject/elnowttx.html