Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

22day 单例模式

$
0
0

1、单例模式的基本实现

/**
 单例模式:一个类只有一个对象
 */
@implementation HLMusicTool

id _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 HSDataTool
static 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;
}
作者:u011018979 发表于2017/7/4 10:51:53 原文链接
阅读:10 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>