您当前的位置: 首页 > 

white camel

暂无认证

  • 3浏览

    0关注

    442博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Objective - C 一一 单例设计模式

white camel 发布时间:2017-07-30 22:46:58 ,浏览量:3

1.什么是设计模式? 

 

在计算机编程语言中有23种设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问,设计模式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样,在iOS中常用的实际模式为:代理方法,MVC模式,MVVC模式,单例模式等。

 

 

什么是单例设计模式?

单例顾名思义就是说一个类的实例只能有一个,在Java、C++这类语言中,可以通过将构造函数私有化来避免对象的重复创建,

但是Objective-C却不能够这样做,我们需要通过其他机制来达到这个目的。

 

我们知道,创建对象的步骤分为申请内存(alloc)、初始化(init)这两个步骤,我们要确保对象的唯一性,

因此在第一步这个阶段我们就要拦截它。当我们调用alloc方法时,oc内部会调用allocWithZone这个方法来申请内存,我们覆写这个方法,

然后在这个方法中调用shareInstance方法返回单例对象,这样就可以达到我们的目的。

拷贝对象也是同样的原理,覆写copyWithZone方法,然后在这个方法中调用shareInstance方法返回单例对象

 

代码如下:

 

#import 

@interface Tools : NSObject
// 一般情况下创建一个单例对象都有一个与之对应的类方法
// 一般情况下用于创建单例对象的方法名称都以share开头, 或者以default开头
+ (instancetype)shareInstance;
@end


#import "Tools.h"

@implementation Tools

+ (instancetype)shareInstance
{
    Tools *instance = [[self alloc] init];
    return instance;
}

// 创建一个空对象
static Tools * _instance = nil;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    
//    // 当前代码在多线程中可能会出现问题(多线程并发问题.出现多个线程同时创建对象,线程不安全)
//    NSLog(@"%s",__func__);
//    // 由于所有的创建方法都会调用该方法, 所以只需要在该方法中控制当前对象只创建一次即可
//    if (_instance == nil) {
//        NSLog(@"创建了一个对象");
//        _instance = [[super allocWithZone:zone] init];
//        
//    }
//    return _instance;
    
    // 线程安全的单例写法
    
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[super allocWithZone:zone] init];
        });
        return _instance;
    
}

// MRC
- (oneway void)release
{
    // 为了保证程序过程中只有一份实例,这个方法什么都不做.
}

- (instancetype)retain
{
    return _instance;
}

- (NSUInteger)retainCount
{
//    return 1;
    // 注意: 为了方便程序员之间沟通,一般情况下不会再单例中返回retainCount = 1;
    // 而是返回一个比较大的值
    return MAXFLOAT;
}

@end

 

 

 

效果如下:

 

main:

#import 
#import "Tools.h"
int main(int argc, const char * argv[]) {
    
    // 单例就是无论怎么创建都只能有一个实例对象
    // 如果地址相同就代表着是同一个实例对象
    
    Tools *t1 = [[Tools alloc] init]; //内部会调用 allocWithZone
    Tools *t2 = [Tools new];          // [[alloc] init]  allocWithZone
    Tools *t3 = [Tools shareInstance];
    NSLog(@"t1 = %p",t1);
    NSLog(@"t2 = %p",t2);
    NSLog(@"t3 = %p",t3);
    
    
//    Tools *t2 = [[Tools alloc] init];
//    [t2 retain];
//    [t2 retain];
//    [t2 retain];
//    [t2 retain];
//    NSLog(@"retainCount = %lu",[t2 retainCount]);
//    NSLog(@"t2 = %p",t2);
//    [t2 release];
//    
//    Tools *t1 = [Tools shareInstance];
//    NSLog(@"t1 = %p",t1);
//    [t1 release];

    
    return 0;
}

 

 

 

输出结果:

ARC输出结果:

 

2017-07-30 23:09:29.707705+0800 单例ARC写法和MRC写法[5474:213457] t1 = 0x100202690
2017-07-30 23:09:29.707915+0800 单例ARC写法和MRC写法[5474:213457] t2 = 0x100202690
2017-07-30 23:09:29.707931+0800 单例ARC写法和MRC写法[5474:213457] t3 = 0x100202690

 

 

MRC输出结果:(上方main方法中,注释的代码打开)

 

2017-07-30 23:10:11.185137+0800 单例ARC写法和MRC写法[5498:213824] retainCount = 4298126752
2017-07-30 23:10:11.185336+0800 单例ARC写法和MRC写法[5498:213824] t2 = 0x1003035a0
2017-07-30 23:10:11.185364+0800 单例ARC写法和MRC写法[5498:213824] t1 = 0x1003035a0

注意:这里我解释一下.在Tools的.m方法中.如果是ARC的情况.不必要重写release,retain,retainCount方法.

 

如果是MRC,要想实现单例,必须重写这个三个方法.

 

从输出结果上来,对象的地址都是一样的,说明是同一块存储空间.这样就只创建了一个对象.

 

 

关注
打赏
1661428283
查看更多评论
立即登录/注册

微信扫码登录

0.0584s