单例模式 singleton
单例模式在OC中很常用,很多代码都有ARC 下的单例模式,也有在非ARC模式下的单例模式。在了解如何进行单例模式的代码书写,首先我们需要知道单例模式到底是什么是单例模式?用在什么场合?
一、什么是单例模式:(Singleton)
二、什么情况下使用单例?
2、一般情况下,多把工具类设计成单例模式
三、非自动内存管理情况下怎么做单例模式.
创建单例设计模式的基本步骤 ·
>声明一个单件对象的静态实例,并初始化为nil。
>创建一个类的类工厂方法,当且仅当这个类的实例为nil时生成一个该类的实例 (工具类,生成类的实例)
>实现NScopying协议, 覆盖allocWithZone:方法,确保用户在直接分配和初始化对象时,不会产 生另一个对象。
>覆盖release、autorelease、retain、retainCount方法, 以此确保单例的状态。
因为单例需要一直存在且计数器永远为 1 ,
所以需要 重写所有 内存管理的方法
>在多线程的环境中,注意使用@synchronized关键字或GCD,确保静态实例被正确的创建和初始化。
下面是代码例子:
//SoundTool.h 头文件
#import <Foundation/Foundation.h>
@interface SoundTool : NSObject <NSCopying> //遵守 NSCoping 协议,必须重写 copyWithZone:方法
+ (instancetype)shareSoundTool;// 类工厂方法,用来生成对象
@end
.m 文件
// SoundTool.m
#import "SoundTool.h"
//非ARC 的单例模式
@implementation SoundTool
//1、自己的静态类
static SoundTool *_soundTool;
//2、allloc只有一次初始化 ,所以重写 allocWithZone:
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
if (_soundTool == nil ) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_soundTool = [super allocWithZone:zone];
});
}
return _soundTool;
}
//3、工具类生成 ,一个单例对象,也只生成一次
+ (instancetype)shareSoundTool
{
return [[self alloc]init];
}
- (id)init// 调用init 之前肯定已经 alloc 了
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_soundTool = [super init];
});
return _soundTool;
}
//4、重写所有内存管理的方法,使之不能改变引用计数的数值
// release retain copyWithZone autoRelease retainCount
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (oneway void)release//异步
{
//什么都不做, 不做计数器 -1
}
- (id)retain
{
return self;// 不做计数器 +1
}
- (instancetype)autorelease //没有发送-1 消息
{
return self;
}
- (NSUInteger)retainCount //计数器数值永远是 1,不变
{
return 1;
}
@end
完成之后,在mian 函数中进行测试:
#import <Foundation/Foundation.h>
#import "SoundTool.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
SoundTool *s1 = [SoundTool shareSoundTool];
SoundTool *s2 = [SoundTool shareSoundTool];
SoundTool *s3 = [s2 copy];
NSLog(@"s1:%p s2:%p s3:%p", s1, s2, s3);
}
return 0;
}
运行结果是:
s1:0x100206ae0 s2:0x100206ae0 s3:0x100206ae0
三个对象都是同一个地址,证明单例模式设计正确。