文档章节

单例类怎么写

风吹筝
 风吹筝
发布于 2016/07/13 16:32
字数 833
阅读 2
收藏 0

 

实现单例类需要满足以下条件:

1.    实现sharedInstance方法、allocWithZone方法

2.    如果有property属性,property的成员变量初始化要放在sharedInstance方法中!!

        不要放在init方法中。

——————————————————探讨过程———————————————————

OC的单例类:

通常在OC中实现一个单例的写法:

static ZZTestObject *instance = nil;
+(instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[[self class] alloc] init];
    });
    return instance;
}

 这时,创建该单例类的对象:

ZZTestObject *object1 = [ZZTestObject sharedInstance];
NSLog(@"object1------------>%@",object1);
ZZTestObject *object2 = [[ZZTestObject alloc] init];
NSLog(@"object2------------->%@",object2);
ZZTestObject *object3 = [ZZTestObject new];
NSLog(@"object3-------------->%@",object3);

测试结果:

2016-07-13 15:13:22.528 SingletonTest[23320:140943] object1------------><ZZTestObject: 0x7fec515253e0>
2016-07-13 15:13:22.528 SingletonTest[23320:140943] object2-------------><ZZTestObject: 0x7fec51512770>
2016-07-13 15:13:22.528 SingletonTest[23320:140943] object3--------------><ZZTestObject: 0x7fec5160cba0>

obviously,这样简单实现的单例类并没有实现单例模式。

 

添加重写allocWithZone方法:

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

得到的输出结果:

2016-07-13 15:33:36.276 SingletonTest[24472:147871] object1------------><ZZTestObject: 0x7faddb505d50>
2016-07-13 15:33:36.276 SingletonTest[24472:147871] object2-------------><ZZTestObject: 0x7faddb505d50>
2016-07-13 15:33:36.276 SingletonTest[24472:147871] object3--------------><ZZTestObject: 0x7faddb505d50>

这样用不同的方式构造,获取的都是同一个对象。

then 给这个单例类添加属性:

@property (nonatomic, assign) NSInteger number;
@property (nonatomic, strong) NSString *str;
@property (nonatomic, strong) NSMutableDictionary *dic;

 

then,重写init和description方法,在init方法中初始化三个成员变量:

- (instancetype)init
{
    self = [super init];
    if (self) {
        _number = 255;
        _str = [[NSString alloc] init];
        _dic = [[NSMutableDictionary alloc] init];
    }
    
    return self;
}



- (NSString *)description
{
    NSString *result = @"";
    result = [result stringByAppendingFormat:@"<%@:%p> \n",[self class],self];
    result = [result stringByAppendingFormat:@"number = %ld \n",self.number];
    result = [result stringByAppendingFormat:@"str = %p \n",self.str];
    result = [result stringByAppendingFormat:@"dic = %p \n",self.dic];
    return result;
}

 

得到的结果如下:

2016-07-13 16:09:32.360 SingletonTest[26562:161389] object1------------><ZZTestObject:0x7fa99b417ee0>
number = 255
str = 0x10cd09470
dic = 0x7fa99b418630
2016-07-13 16:09:32.360 SingletonTest[26562:161389] object2-------------><ZZTestObject:0x7fa99b417ee0>
number = 255
str = 0x10cd09470
dic = 0x7fa99b712160
2016-07-13 16:09:32.360 SingletonTest[26562:161389] object3--------------><ZZTestObject:0x7fa99b417ee0>
number = 255
str = 0x10cd09470
dic = 0x7fa99b58d270

 

 

尽管是同一个单例对象,但得到的三个property属性值却不尽相同

虽然没有为单例对象重新分配内存空间,但是又执行了init方法,导致成员变量重新初始化

 

————————————————华丽丽的分割线—————————————————

下面修改成员变量的初始化位置

static ZZTestObject *instance = nil;
+(instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[[self class] alloc] init];//也可以用[super init]
        instance.number = 255;
        instance.str = [[NSString alloc] init];
        instance.dic = [[NSMutableDictionary alloc] init];

    });
    return instance;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
//        _number = 255;
//        _str = [[NSString alloc] init];
//        _dic = [[NSMutableDictionary alloc] init];
    }
    
    return self;
}

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

- (NSString *)description
{
    NSString *result = @"";
    result = [result stringByAppendingFormat:@"<%@:%p> \n",[self class],self];
    result = [result stringByAppendingFormat:@"number = %ld \n",self.number];
    result = [result stringByAppendingFormat:@"str = %p \n",self.str];
    result = [result stringByAppendingFormat:@"dic = %p \n",self.dic];
    return result;
}

得到的结果:

2016-07-13 16:17:52.575 SingletonTest[27035:165712] object1------------><ZZTestObject:0x7fe7cb718d00>
number = 255
str = 0x101b1a470
dic = 0x7fe7cb717ab0
2016-07-13 16:17:52.575 SingletonTest[27035:165712] object2-------------><ZZTestObject:0x7fe7cb718d00>
number = 255
str = 0x101b1a470
dic = 0x7fe7cb717ab0
2016-07-13 16:17:52.575 SingletonTest[27035:165712] object3--------------><ZZTestObject:0x7fe7cb718d00>
number = 255
str = 0x101b1a470
dic = 0x7fe7cb717ab0

可以看到 得到的结果是一样的

————————————————总结要来了——————————————————

总结:

实现单例类需要满足以下条件:

1.    实现上述的sharedInstance方法、allocWithZone方法

2.    如果有property属性,property的成员变量初始化要放在sharedInstance方法中!!

        不要放在init方法中。

———————————————————————————————————————

祝我们都能写出准确的单例类。

© 著作权归作者所有

上一篇: NSError
风吹筝
粉丝 0
博文 5
码字总数 1593
作品 0
杭州
私信 提问
延迟加载单例模式(IoDH)引发的NoClassDefFoundError

一、问题背景 最近题主发布在公司的SDK遇到了一个Bug。有关单例模式的,什么问题呢? 我们先回想下,单例模式怎么写。(https://www.jianshu.com/p/f71fabb46233) 简而言之: 私有的构造方法...

唐影若凡
2018/01/18
0
0
iOS严谨单例写法/可继承单例

单例模式在iOS开发中可能算是最常用的模式之一了,但是由于OC本身的语言特性,想要写一个正确的单例模式相对来说比较麻烦. 今天就来说一说, 单例创建的方式和严谨的单例写法及可继承单例编写...

云上飞飞
2016/10/10
80
0
JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是c...

刘桂林
2016/06/06
0
0
单例模式 - Singleton Pattern

简介 什么是单例?为什么需要单例? 单例模式的目的是设计出一个类,能提供全局唯一的对象。 举个例子,程序中需要一个类用做管理配置项。这样一个类显然希望是全局只有一个,在任何地方都能...

齐晋
2017/08/22
0
0
【转】可能继承的C++ Singleton基类

from:http://www.gocalf.com/blog/cpp-singleton.html 单例模式(Singleton Pattern)是设计模式中的一种,它用来保证系统中最多只能存在一个它的实例,其做法是由类自身来创建和持有它的对象...

夏春涛
2012/08/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Boot + Mybatis-Plus 集成与使用(二)

前言: 本章节介绍MyBatis-Puls的CRUD使用。在开始之前,先简单讲解下上章节关于Spring Boot是如何自动配置MyBatis-Plus。 一、自动配置 当Spring Boot应用从主方法main()启动后,首先加载S...

伴学编程
昨天
7
0
用最通俗的方法讲spring [一] ──── AOP

@[TOC](用最通俗的方法讲spring [一] ──── AOP) 写这个系列的目的(可以跳过不看) 自己写这个系列的目的,是因为自己是个比较笨的人,我曾一度怀疑自己的智商不适合干编程这个行业.因为在我...

小贼贼子
昨天
7
0
Flutter系列之在 macOS 上安装和配置 Flutter 开发环境

本文为Flutter开发环境在macOS下安装全过程: 一、系统配置要求 想要安装并运行 Flutter,你的开发环境需要最低满足以下要求: 操作系统:macOS(64位) 磁盘空间:700 MB(不包含 IDE 或其余...

過愙
昨天
6
0
OSChina 周六乱弹 —— 早上儿子问我他是怎么来的

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @凉小生 :#今日歌曲推荐# 少点戾气,愿你和这个世界温柔以待。中岛美嘉的单曲《僕が死のうと思ったのは (曾经我也想过一了百了)》 《僕が死の...

小小编辑
昨天
2.7K
16
Excption与Error包结构,OOM 你遇到过哪些情况,SOF 你遇到过哪些情况

Throwable 是 Java 中所有错误与异常的超类,Throwable 包含两个子类,Error 与 Exception 。用于指示发生了异常情况。 Java 抛出的 Throwable 可以分成三种类型。 被检查异常(checked Exc...

Garphy
昨天
42
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部