iOS学习笔记-112.多线程11——单例设计模式

多线程11——单例设计模式

一、说明

种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

1、单例类只能有一个实例。

2、单例类必须自己创建自己的唯一实例。

3、单例类必须给所有其他对象提供这一实例。

单例模式


二、ARC下的单例模式

由于不是我们自己管理内存,所以不用考虑释放的问题。这种情况下,我们创建一个类方法,让外界获取我们的实例对象。然后重写我们创建实例的方法
我们创建的单例如下

2.1 SingleArc

2.1.1 SingleArc.h
//
//  SingleArc.h
//  03_UIview84多线程_单例模式
//
//  Created by 杞文明 on 17/9/3.
//  Copyright © 2017年 杞文明. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface SingleArc : NSObject
/*外部获取实例的方法*/
+(instancetype)shareSingle;
@end
2.1.2 SingleArc.m
//
//  SingleArc.m
//  03_UIview84多线程_单例模式
//
//  Created by 杞文明 on 17/9/3.
//  Copyright © 2017年 杞文明. All rights reserved.
// 自动管理的 单例模式 
//

#import "SingleArc.h"

@implementation SingleArc

static SingleArc *_instance;

+(instancetype)allocWithZone:(struct _NSZone *)zone{
//   //考虑线程安全可以使用互斥锁
//    @synchronized (self) {
//        if(_instance==nil){
//            _instance = [super allocWithZone:zone];
//        }
//    }
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}

+(instancetype)shareSingle{
    return [[self alloc]init];
}

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

-(id)mutableCopyWithZone:(NSZone*)zone{
    return _instance;
}

@end

2.2 代码示例

/*ARC 单例模式测试*/
-(void)singleArcTest{
    SingleArc *s1 = [[SingleArc alloc]init];
    SingleArc *s2 = [[SingleArc alloc]init];
    SingleArc *s3 = [SingleArc new];
    SingleArc *s4 = [SingleArc shareSingle];
    SingleArc *s5 = [s1 copy];
    SingleArc *s6 = [s2 mutableCopy];

    NSLog(@"s1 -- %@",s1);
    NSLog(@"s2 -- %@",s2);
    NSLog(@"s3 -- %@",s3);
    NSLog(@"s4 -- %@",s4);
    NSLog(@"s5 -- %@",s5);
    NSLog(@"s6 -- %@",s6);
}

2.3 运行结果

[20863:94340] s1 -- <SingleArc: 0x608000007a20>
[20863:94340] s2 -- <SingleArc: 0x608000007a20>
[20863:94340] s3 -- <SingleArc: 0x608000007a20>
[20863:94340] s4 -- <SingleArc: 0x608000007a20>
[20863:94340] s5 -- <SingleArc: 0x608000007a20>
[20863:94340] s6 -- <SingleArc: 0x608000007a20>

我们可以看到我们所有的对象都是同一个。


二、ARC和MRC切换

这里写图片描述


四、MRC下的单例模式

由于使我们自己管理内存,这里面我们会调用 release等方法。这样我们创建的实例被释放了,接下来我们就不能用了,因此我们在MRC下需要重写这些方法

4.1 SingleMrc

4.1.1 SingleMrc.h
//
//  SingleMrc.h
//  03_UIview84多线程_单例模式
//
//  Created by 杞文明 on 17/9/3.
//  Copyright © 2017年 杞文明. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface SingleMrc : NSObject

+(instancetype)shareSingleMrc;

@end
4.1.2 SingleMrc.m
//
//  SingleMrc.m
//  03_UIview84多线程_单例模式
//
//  Created by 杞文明 on 17/9/3.
//  Copyright © 2017年 杞文明. All rights reserved.
//
// 手动管理的 单例模式
#import "SingleMrc.h"

@implementation SingleMrc

static SingleMrc *_instance;

/*重写创建实例的方法*/
+(instancetype)allocWithZone:(struct _NSZone *)zone{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}

+(instancetype)shareSingleMrc{
    return [[SingleMrc alloc]init];
}

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

-(id)mutableCopyWithZone:(NSZone*)zone{
    return _instance;
}

//MRC方式下,我们得重写下面的方法

-(oneway void)release{
}

-(instancetype)retain{
    return _instance;
}

/*引用计数器设置为最大值*/
-(NSUInteger)retainCount{
    return MAXFLOAT;
}

@end

4.2 代码示例

/*MRC 单例模式测试*/
-(void)singleMrcTest{
    SingleMrc *s1 = [[SingleMrc alloc]init];
    [s1 release];
    SingleMrc *s2 = [[SingleMrc alloc]init];
    [s1 release];
    SingleMrc *s3 = [SingleMrc new];
    [s1 release];
    SingleMrc *s4 = [SingleMrc shareSingleMrc];
    [s1 release];
    SingleMrc *s5 = [s1 copy];
    [s1 release];
    SingleMrc *s6 = [s2 mutableCopy];
    [s1 release];

    NSLog(@"s1 -- %@",s1);
    NSLog(@"s2 -- %@",s2);
    NSLog(@"s3 -- %@",s3);
    NSLog(@"s4 -- %@",s4);
    NSLog(@"s5 -- %@",s5);
    NSLog(@"s6 -- %@",s6);
}

4.3 运行结果

[28259:136270] s1 -- <SingleMrc: 0x60000001a8f0>
[28259:136270] s2 -- <SingleMrc: 0x60000001a8f0>
[28259:136270] s3 -- <SingleMrc: 0x60000001a8f0>
[28259:136270] s4 -- <SingleMrc: 0x60000001a8f0>
[28259:136270] s5 -- <SingleMrc: 0x60000001a8f0>
[28259:136270] s6 -- <SingleMrc: 0x60000001a8f0>

五、ARC和MRC都能使用的单例模式

这二者的区别就是要不要重写以下的方法

-(oneway void)release;

-(instancetype)retain;

-(NSUInteger)retainCount;

那么我们的操作也是非常简单,只需要判断是 ARC 还是 MRC ,MRC下我们重写这些方法。

那么怎么判断呢?

我们可以使用以下的代码判断

#if __has_feature(objc_arc)
//ARC
#else
//MRC
#elseif

5.1 SingleAMrc

5.1.1 SingleAMrc.h
//
//  SingleAMrc.h
//  03_UIview84多线程_单例模式
//
//  Created by 杞文明 on 17/9/3.
//  Copyright © 2017年 杞文明. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface SingleAMrc : NSObject
+(instancetype)shareSingleAMrc;
@end
5.1.2 SingleAMrc.m
//
//  SingleAMrc.m
//  03_UIview84多线程_单例模式
//
//  Created by 杞文明 on 17/9/3.
//  Copyright © 2017年 杞文明. All rights reserved.
//

#import "SingleAMrc.h"

@implementation SingleAMrc

//-----------下面这部分是ARC和MRC都是共有的------------

static SingleAMrc *_instance;

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

+(instancetype)shareSingleAMrc{
    return _instance;
}

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

-(id)mutableCopyWithZone:(NSZone*)zone{
    return _instance;
}

//----------下面这部分是MRC特有的------------
//编译判断,如果是MRC我们才去操作

#if __has_feature(objc_arc)//如果是ARC不操作
//ARM
#else//如果是MRC重写我们的方法
//MRC

-(oneway void)release{
}

-(instancetype)retain{
    return _instance;
}

-(NSUInteger)retainCount{
    return MAXFLOAT;
}
#endif

@end

5.2 代码示例

我们的测试实在 MRC 下的

/*ARC和MRC都行的 单例模式测试*/
-(void)singleAMrcTest{
    SingleAMrc *s1 = [[SingleAMrc alloc]init];
    [s1 release];
    SingleAMrc *s2 = [[SingleAMrc alloc]init];
    [s2 release];
    SingleAMrc *s3 = [SingleAMrc new];
    [s3 release];
    SingleAMrc *s4 = [SingleAMrc shareSingleAMrc];
    [s4 release];
    SingleAMrc *s5 = [s1 copy];
    [s5 release];
    SingleAMrc *s6 = [s2 mutableCopy];
    [s6 release];

    NSLog(@"s1 -- %@",s1);
    NSLog(@"s2 -- %@",s2);
    NSLog(@"s3 -- %@",s3);
    NSLog(@"s4 -- %@",s4);
    NSLog(@"s5 -- %@",s5);
    NSLog(@"s6 -- %@",s6);
}

5.3 运行结果

[29747:143162] s1 -- <SingleAMrc: 0x6000000010b0>
[29747:143162] s2 -- <SingleAMrc: 0x6000000010b0>
[29747:143162] s3 -- <SingleAMrc: 0x6000000010b0>
[29747:143162] s4 -- <SingleAMrc: 0x6000000010b0>
[29747:143162] s5 -- <SingleAMrc: 0x6000000010b0>
[29747:143162] s6 -- <SingleAMrc: 0x6000000010b0>

六、宏定义单例模式模板

如果我们想要创建多个类的单例模式,那么我们发现代码基本是一样的,最多就是类的名字不一样。那么我们可以不可以简单点来实现呢??

我们可以定义宏来实现,宏之间的连接符使用

/

参数拼接使用

##

那么我们在定义我们的内部静态变量的时候怎么弄呢?

我们可以使用id

如下

static SingleAMrc *_instance;

可以改为

static id _instance;

我们获取实例的方法,方法名的后半部分是不一样的,那么我们怎么解决呢?

我们可以使用宏传递参数过来,然后拼接

如下

+(instancetype)shareSingleAMrc;

可以改为

#define SingleH(name) +(instancetype)share##name;

那么我们怎么解决ARC和MRC呢?

我们可以在判断里面重写代码

如下

#if
//ARC下的方法
#else
//MRC下的方法
#elseif

6.1 Single.h 宏定义的头文件

//
//  Single.h
//  03_UIview84多线程_单例模式
//
//  Created by 杞文明 on 17/9/3.
//  Copyright © 2017年 杞文明. All rights reserved.
//

#define SingleH(name) +(instancetype)share##name;

#if __has_feature(objc_arc)
//ARC
#define SingleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
\
return _instance;\
}\
\
+(instancetype)share##name\
{\
return [[self alloc]init];\
}\
\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}

#else
//MRC
#define SingleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
\
return _instance;\
}\
\
+(instancetype)share##name\
{\
return [[self alloc]init];\
}\
\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
-(oneway void)release\
{\
}\
\
-(instancetype)retain\
{\
return _instance;\
}\
\
-(NSUInteger)retainCount\
{\
return MAXFLOAT;\
}

#endif

6.2 使用宏定义Single.h创建工具类QWMTool

6.2.1 QWMTool.h
//
//  QWMTool.h
//  03_UIview84多线程_单例模式
//
//  Created by 杞文明 on 17/9/3.
//  Copyright © 2017年 杞文明. All rights reserved.
//

#import <Foundation/Foundation.h>
#include "Single.h"

@interface QWMTool : NSObject
SingleH(Tool)
@end
6.2.1 QWMTool.m
//
//  QWMTool.m
//  03_UIview84多线程_单例模式
//
//  Created by 杞文明 on 17/9/3.
//  Copyright © 2017年 杞文明. All rights reserved.
//

#import "QWMTool.h"

@implementation QWMTool
SingleM(Tool)
@end

6.3 QWMTool示例代码

ARC下测试的

/* 宏定义的单例模式测试*/
-(void)qwmtoolTest{
    QWMTool *t1 = [[QWMTool alloc]init];
    QWMTool *t2 = [[QWMTool alloc]init];
    QWMTool *t3 = [QWMTool new];
    QWMTool *t4 = [QWMTool shareTool];
    QWMTool *t5 = [t1 copy];
    QWMTool *t6 = [t2 mutableCopy];

    NSLog(@"t1 -- %@",t1);
    NSLog(@"t2 -- %@",t2);
    NSLog(@"t3 -- %@",t3);
    NSLog(@"t4 -- %@",t4);
    NSLog(@"t5 -- %@",t5);
    NSLog(@"t6 -- %@",t6);
}

6.4 QWMTool测试运行结果

[32260:152900] t1 -- <QWMTool: 0x608000017680>
[32260:152900] t2 -- <QWMTool: 0x608000017680>
[32260:152900] t3 -- <QWMTool: 0x608000017680>
[32260:152900] t4 -- <QWMTool: 0x608000017680>
[32260:152900] t5 -- <QWMTool: 0x608000017680>
[32260:152900] t6 -- <QWMTool: 0x608000017680>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值