iOS启蒙iOS学习开发iOS学习笔记

iOS 设计模式: Singleton – 单例模式

2017-02-19  本文已影响62人  孟豊Mike

单例 的意思就是确保在程序运行过程中只创建一个对象实例,而可以被多次使用。如我们常见的网络请求类、工具类、和其他管理类等。作为一个iOS开发者,我们经常和单例打交道,比如:[NSUserDefaults standerUserDefaults], [UIApplication sharedApplication],[UIScreen mainScreen], [NSFileManager defaultManager]返回的都是单例对象。
我们在开源项目、苹果示例代码能见到无数使用单例的例子。Xcode 甚至有默认的 "Dispatch Once" 代码片段,使我们可以非常简单地在代码中添加一个单例。

"Dispatch Once" 代码片段

一、单例的作用

注意点!!!! 单例应该只用来保存全局的状态,并且不能和任何作用域绑定。如果这些状态的作用域比一个完整的应用程序的生命周期要短,那么这个状态就不应该使用单例来管理。因为单例从创建后到彻底关闭程序前都会一直存在,如果过多的创建单例无疑浪费系统资源和影响系统效率

二、单例的三要点

1. 该类有且只有一个实例;(类的构造方法是私有的我们只需要重写allocWithZone方法,让初始化操作只执行一次)

2. 该类必须能够自行创建这个实例;(类提供一个类方法产生对象)

3. 该类必须能够自行向整个系统提供这个实例。(类中有一个私有的自己对象我们可以在.m文件中定义一个属性即可)

三、单例的实现步骤

1. 为单例对象创建一个静态实例,可以写成全局的,也可以在类方法里面实现,并初始化为nil;
  2. 提供一个类方法,方便外界访问;
  3. 重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不产生一个新实例;
  4. 重写-copyWithZone方法和-MutableCopyWithZone方法

一般创建对象的步骤分为申请内存(alloc)、初始化(init)这两个步骤,我们要确保对象的唯一性,所以要在第一步拦截它。当我们调用alloc方法时,oc内部会调用allocWithZone这个方法来申请内存,我们覆写这个方法,然后在这个方法中调用shareInstance方法返回单例对象,这样就可以达到我们的目的。拷贝对象也是同样的原理,覆写copyWithZone方法,然后在这个方法中调用shareInstance方法返回单例对象。

#import "Tools.h"

@implementation Tools
// 创建静态对象 防止外部访问
static Tools *_instance;
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
    @synchronized (self) {
        // 为了防止多线程同时访问对象,造成多次分配内存空间,所以要加上线程锁
        if (_instance == nil) {
           _instance = [super allocWithZone:zone];
      }
      return _instance;
}
// 为了使实例易于外界访问 我们一般提供一个类方法
// 类方法命名规范 share类名|default类名|类名
+(instancetype)shareTools
{
    //return _instance;
    // 最好用self 用Tools他的子类调用时会出现错误
    return [[self alloc]init];
}
// 为了严谨,也要重写copyWithZone 和 mutableCopyWithZone
-(id)copyWithZone:(NSZone *)zone
{
    return _instance;
}
-(id)mutableCopyWithZone:(NSZone *)zone
{
    return _instance;
}

也可以使用Xcode 默认的dispatch_once代码片段用 GCD的方式创建:
@implementation Singleton
static id _instance;

+ (instancetype)allocWithZone:(struct _NSZone *)zone{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}

+ (instancetype)sharedSingleton{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}

- (id)copyWithZone:(NSZone *)zone{
    return _instance;
}
@end

四、使用单例的注意事项

上一篇下一篇

猜你喜欢

热点阅读