iOS开发---单例浅析

2019-06-20  本文已影响0人  Cary_Xu

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。

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

二、什么是单例

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

  简而言之

三、如何实现单例

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

+ (CYSingleTest *)sharedInstance
{
    //为了隔离外部修改在sharedInstance中设置静态变量_instance
    static CYSingleTest *_instance = nil;
    //考虑多线程问题
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:nil];
    });
    
    return _instance;
    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开发中的常用的设计模式

上一篇下一篇

猜你喜欢

热点阅读