22day 单例模式

来源:互联网 发布:2016淘宝客如何推广 编辑:程序博客网 时间:2024/06/13 12:42

1、单例模式的基本实现

/** 单例模式:一个类只有一个对象 */@implementation HLMusicToolid _musicTool;//全局变量/** alloc方法内部会调用这个方法 */+ (instancetype)allocWithZone:(struct _NSZone *)zone{    NSLog(@"%s",__func__);    @synchronized(self) {//多线程        //创建对象的内存空间        if (nil == _musicTool) {            _musicTool = [super allocWithZone:zone];        }    }    return _musicTool;}/** 方便访问单例对象*/+ (instancetype)sharedMusicTool{    @synchronized(self) {        //操作共享资源        if (nil == _musicTool) {            _musicTool = [[self alloc]init];        }    }    return _musicTool;}/**     NSLog(@"%@",[[[HLMusicTool alloc]init] copy]);//Returns the object returned by copyWithZone:.  copyWithZone  遵守协议NSCopying*/- (id)copyWithZone:(nullable NSZone *)zone{    return _musicTool;}

2、单例模式的完善

解决:
1)extern 对全局变量的引用 :,会在全程序中查找 _musicTool,:在其他类引用全局变量,其他类就可以修改全局变量的值,导致单例对象存在被修改的风险

解决办法就是使用static 进行修饰

2)防止多次加锁: 只有在确实需要创建对象的时候,才进行加锁。即加锁之前先进行是否满足创建对象的条件

/* static 修饰变量: 1)static的局部变量:保证只初始化一次,在程序运行过程中只有一份内容;--局部变量的生命周期和全局变量类似,但是不能改变作用域 2)static 修饰的全局变量:不允许本类的h文件访问。即作用域仅限于当前的文件 ps:在其他类引用全局变量,其他类就可以修改全局变量的值,导致单例对象存在被修改的风险 extern id _musicTool; 引用全局变量,会在全程序中查找 _musicTool 解决方法:static 修饰的全局变量,这样其他类就无法引用extern*/ static id _musicTool;//全局变量/** alloc方法内部会调用这个方法 */+ (instancetype)allocWithZone:(struct _NSZone *)zone{    NSLog(@"%s",__func__);    if (nil == _musicTool) {        @synchronized(self) {//多线程            //创建对象的内存空间            if (nil == _musicTool) {                _musicTool = [super allocWithZone:zone];            }        }    }    return _musicTool;}/** 方便放回单例对象*/+ (instancetype)sharedMusicTool{    if (_musicTool == nil) {//防止频繁加锁        //加锁        @synchronized(self) {            //操作共享资源            if (nil == _musicTool) {//防止创建多次                _musicTool = [[self alloc]init];            }        }    }    return _musicTool;}/**     NSLog(@"%@",[[[HLMusicTool alloc]init] copy]);//Returns the object returned by copyWithZone:.  copyWithZone  遵守协议NSCopying*/- (id)copyWithZone:(nullable NSZone *)zone{    return _musicTool;}

3、GCD和宏实现单例-- 宏定义的代码不好调试

1).ARC 环境下的GCD实现单例

/*GCD 实现单例*/static id _dataTool;+ (instancetype)shareDataTool{    //GCD    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{//一次性代码        _dataTool = [[self alloc]init];    });    return _dataTool;}+ (instancetype)allocWithZone:(struct _NSZone *)zone{    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        _dataTool = [super allocWithZone:zone];    });   return _dataTool;}- (id)copyWithZone:(NSZone *)zone{    return _dataTool;}

2)、非ARC的单例模式

release重写,进行阻止单例对象的释放

@implementation HSDataToolstatic id _dataTool;+(instancetype)shareDataTool{    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        _dataTool = [[HSDataTool alloc]init];    });    return _dataTool;}- (id)copyWithZone:(NSZone *)zone{    return _dataTool;}+ (instancetype)allocWithZone:(struct _NSZone *)zone{    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        _dataTool = [super allocWithZone:zone];        NSLog(@"%s",__func__);    });    return _dataTool;}#pragma mark - MRC环境的适配:重写/* Decrements the receiver’s reference count. The receiver is sent a dealloc message when its reference count reaches 0. */- (oneway void)release{}- (instancetype)retain{    return self;}- (NSUInteger)retainCount{    return 1;}

3.GCD和宏 来实现单例

#ifndef HSSingleton_h#define HSSingleton_h//头文件的单例内容#define HSSingletonH(classname) +(instancetype)share##classname//.m文件的单例代码#define HSSingletonM(classname) \static id _instance;\+(instancetype)share##classname{\    static dispatch_once_t onceToken;\    dispatch_once(&onceToken, ^{\        _instance = [[self alloc]init];\    });\    return _instance;\}\- (id)copyWithZone:(NSZone *)zone{\    return _instance;\}\+ (instancetype)allocWithZone:(struct _NSZone *)zone{\    static dispatch_once_t onceToken;\    dispatch_once(&onceToken, ^{\        _instance = [super allocWithZone:zone];\    });\    return _instance;\}\- (oneway void)release{\}\- (instancetype)retain{\    return self;\}\- (NSUInteger)retainCount{\    return 1;\}#endif /* HSSingleton_h */

4、ARC、MRC的适配(条件编译)

//头文件的单例内容#define HSSingletonH(classname) +(instancetype)share##classname//.m文件的单例代码#if __has_feature(objc_arc)#define HSSingletonM(classname) \static id _instance;\+(instancetype)share##classname{\static dispatch_once_t onceToken;\dispatch_once(&onceToken, ^{\_instance = [[self alloc]init];\});\return _instance;\}\- (id)copyWithZone:(NSZone *)zone{\return _instance;\}\+ (instancetype)allocWithZone:(struct _NSZone *)zone{\static dispatch_once_t onceToken;\dispatch_once(&onceToken, ^{\_instance = [super allocWithZone:zone];\});\return _instance;\}#else#define HSSingletonM(classname) \static id _instance;\+(instancetype)share##classname{\    static dispatch_once_t onceToken;\    dispatch_once(&onceToken, ^{\        _instance = [[self alloc]init];\    });\    return _instance;\}\- (id)copyWithZone:(NSZone *)zone{\    return _instance;\}\+ (instancetype)allocWithZone:(struct _NSZone *)zone{\    static dispatch_once_t onceToken;\    dispatch_once(&onceToken, ^{\        _instance = [super allocWithZone:zone];\    });\    return _instance;\}\- (oneway void)release{\}\- (instancetype)retain{\    return self;\}\- (NSUInteger)retainCount{\    return 1;\}\- (instancetype)autorelease{\    return self;\}#endif

5、、饿汉式(了解)

/* ninitailize、load方法的区别: initailize、load都是类方法 当一个类 或者分类被装载进内存时,就会调用一次load方法(当时这个类还不可用) 当第一次使用这个类时,就会调用一次initailize方法*//**  Invoked whenever a class or category is added to the Objective-C runtime;  因此不存在多线程问题*/+ (void)load{    _instance = [[HLSoundTool alloc]init];    NSLog(@"%s----instance%@",__func__,_instance);}//+ (void)initialize{//    NSLog(@"%s",__func__);//}+ (instancetype)allocWithZone:(struct _NSZone *)zone{    if (_instance == nil) {        _instance = [super allocWithZone:zone];    }    return _instance;}- (id)copyWithZone:(NSZone *)zone{    return _instance;}+(instancetype)shareSoundTool{    return _instance;}
原创粉丝点击