美文网首页
iOS开发---单例浅析

iOS开发---单例浅析

作者: Cary_Xu | 来源:发表于2019-06-20 17:12 被阅读0次

    Ensures a class has only one instance, and provide a global point of access to it.
    『确保一个类有且只有一个实例,并提供一个全局点去访问它。』
                              ---四人组(GoF)

    一、设计模式

      设计模式(Design pattern)从总体来说可以分为三大类:
      创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
      结构型模式(7):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
      行为型模式(11):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

    而我们iOS中常用的几种设计模式有:代理模式、观察者模式、MVC模式、单例模式、策略模式、工厂模式、MVVM。

      今天我们共同探讨一下单例模式。其他几种设计模式有机会另行讨论。

    二、什么是单例

    单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的一个类只有一个实例。即一个类只有一个对象实例。
                                ---百度百科

      简而言之

    • 1、它是一种常用的软件设计模式
    • 2、程序运行过程,一个类只有一个实例,且该类可供外界访问,从而方便地控制实例个数,并节约系统资源
    • 3、在整个应用程序中,共享一份资源

    三、如何实现单例

      根据前面对单例模式的定义我们知道,程序中必须能方便的控制一个类有且只有一个实例。且该类可供外界访问。
      废话少说,上子弹。

    • 1、用工厂方法创建对象,提供统一的创建方法给外部使用
    + (CYSingleTest *)sharedInstance
    {
        //为了隔离外部修改在sharedInstance中设置静态变量_instance
        static CYSingleTest *_instance = nil;
        //考虑多线程问题
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [super allocWithZone:nil];
        });
        
        return _instance;
    
    • 2、控制一个类有且只有一个实例
        CYSingleTest *singleTest0 = [CYSingleTest sharedInstance];
        CYSingleTest *singleTest1 = [[CYSingleTest alloc] init];
        CYSingleTest *singleTest2 = [CYSingleTest new];
    

      以上是创建一个CYSingleTest实例的三种常用方式,我们打印一下看看结果:
    singleTest0===<CYSingleTest: 0x6000021a8350>
    singleTest1===<CYSingleTest: 0x6000021a84f0>
    singleTest2===<CYSingleTest: 0x6000021a84e0>
      通过结果我们发现上述三种方式实际上是创建了三个不同的实例,不满足要求,继续优化。

      由Objective-C的一些特性可知,在创建对象的时候,无论是alloc还是new,都会调用以下方法。

    + (id)allocWithZone:(struct _NSZone *)zone
    

      因此,可以重写这些方法,让创建的对象唯一。

    + (id)allocWithZone:(struct _NSZone *)zone
    {
        return [CYSingleTest sharedInstance];
    }
    

      我们再打印一下看看结果:
    singleTest0===<CYSingleTest: 0x6000031c4340>
    singleTest1===<CYSingleTest: 0x6000031c4340>
    singleTest2===<CYSingleTest: 0x6000031c4340>
      大功告成!
      你以为故事到这里就告一段落了么?并没有!
      除了上述三种创建对象的方式,我们常常还会用到copy和mutableCopy。

    CYSingleTest *single3 = [single2 copy];
    CYSingleTest *single4 = [single2 mutableCopy];
    

       重点来了!
       重点来了!
       重点来了!
       此时直接运行程序会报错:
    -[CYSingleTest copyWithZone:]: unrecognized selector sent to instance 0x6000035c6da0
      再由Objective-C的一些特性可知,在通过拷贝的方式创建对象时,会调用以下方法:

    - (id)copyWithZone:(struct _NSZone *)zone
    - (id)mutableCopyWithZone:(struct _NSZone *)zone
    

      所以我们再重写两个拷贝方法:

    - (id)copyWithZone:(struct _NSZone *)zone
    {
        return [CYSingleTest sharedInstance];
    }
    - (id)mutableCopyWithZone:(struct _NSZone *)zone
    {
        return [CYSingleTest sharedInstance];
    }
    

      注意:

    //重写copy的相关方法时必须引入copy的相关文件
    //表示该类遵守NSCopying、NSMutableCopying协议
    @interface CYSingleTest : NSObject<NSCopying,NSMutableCopying>
    

      我们最后打印一下看看结果:
    singleTest0===<CYSingleTest: 0x600000388190>
    singleTest1===<CYSingleTest: 0x600000388190>
    singleTest2===<CYSingleTest: 0x600000388190>
    singleTest3===<CYSingleTest: 0x600000388190>
    singleTest4===<CYSingleTest: 0x600000388190>
      OK,打完收工!

    四、总结

      一个项目往往不止一个单例,所以我们可以将以上方法整理成宏定义或者代码块,这样我们以后使用的时候就会更加得心应手。具体操作这里就不再赘述了。

    知识拓展:
    iOS设计模式详解
    iOS开发中的几种设计模式
    java开发中的常用的设计模式

    相关文章

      网友评论

          本文标题:iOS开发---单例浅析

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