书写一个严谨的单例

简介: 什么是单例?一个类只有一个实例(一个对象),而且该实例易于供外界访问,从而方便地控制了实例个数,并节约系统资源

前言

什么是单例?

一个类只有一个实例(一个对象),而且该实例易于供外界访问,从而方便地控制了实例个数,并节约系统资源

正题

在iOS开发中单例是很平常的模式,但是昨天去面试的时候被人问到了一个比较尴尬的问题。
平常在项目中我们书写的单例大概应该都是这个样子,现在.h文件中声明一个类方法

@implementation Singleton

+(instancetype)shareInstance;

@end

然后在.m中去实现这个方法

@implementation Singleton

static Singleton *instance = nil;

+(instancetype)shareInstance{
    static dispatch_once_t onceToken;
    dispath_once(&onceToken,^{
        instance = [[self alloc]init];
    });
    return instance;
}

但是,昨天有人问了这么一个问题,说一般的都知道这个类方法是创建单例的,假如我不知道,我直接走了[[self alloc]init]方法来创建这个对象。那是不是就不能保证这个对象类的唯一性了?
仔细想一下好像是这样,这也是我个人的问题。在写项目的时候没有注意到这么个问题。在当时那个是时候我是被难住了......
之后我就写了一个demo试了一下

单例
这时我们再看看控制台中打印出来的信息

single1single2的地址是一样的,因为都是走了那个类方法,可是single3就不一样了,这个时候这个Singleton就不严谨了。

解决问题

之后我就去网上找了一下,网上真的有很多人已经写过这样的技术博客了。我就去试了试。
主要就是为了确保对象的唯一性,所以我们需要封锁用户通过alloc和init以及copy来构造对象的这条路。
在创建对象的时候主要分这么两步 alloc (申请内存)init(初始化)
1.我们在第一步alloc的会后就要对其进行拦截。当我们去调用alloc的时候,OC内部会调用allocWithZone这个方法去申请内存,我们去覆写这个方法,然后在这个方法中调用之前的类方法,返单例对象,这样就能达到我们的目的了。
2.拷贝对象也是一样的,覆写copyWithZone方法,然后在方法中去调用类方法,返回单例对象。(在覆写copyWithZone方法之前别忘记了签署NSCopying协议)

类方法中也有做些许改动

#import <Foundation/Foundation.h>

@interface Singleton : NSObject<NSCopying>

+(instancetype)sharedInstance;

@end
#import "Singleton.h"

@implementation Singleton

static Singleton *instance = nil;

+(instancetype)sharedInstance{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken,^{
//        instance = [[self alloc]init];
        instance = [[super allocWithZone:NULL]init];
    });
    return instance;
}
+(id)allocWithZone:(struct _NSZone *)zone{
    return [Singleton sharedInstance];
}
-(id)copyWithZone:(NSZone *)zone{
    return [Singleton sharedInstance];
}
@end

接下来我们再看看通过不同方式创建之后的地址是否相同


控制台的输出

声明

本人并不是一个技术大神,只是一个菜鸟而已,写这个文章也不是为了炫耀什么,只是记录一下自己工作中的问题&如何解决。

相关文章
|
2月前
|
自然语言处理 算法 Java
C/C++ 程序员编程规范之注释
C/C++ 程序员编程规范之注释
47 1
|
6月前
|
存储 编译器 C++
漫谈 C++:良好的编程习惯与编程要点
以良好的方式编写C++ class 假设现在我们要实现一个复数类complex,在类的实现过程中探索良好的编程习惯。既然函数不会改变对象,那么就如实说明,编译器能帮你确保函数的const属性,阅读代码的人也明确你的意图
63 1
漫谈 C++:良好的编程习惯与编程要点
|
7月前
|
人工智能 前端开发 JavaScript
【炫技的代码写法】
【炫技的代码写法】
|
9月前
|
XML 安全 Java
教你精通Java语法之第十三章、反射
Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到,那么,我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制。1. 反射的意义2. 反射重要的几个类: Class类 、Field类、 Method类、 Constructor类3. 学会合理利用反射,一定要在安全环境下使用。
39 0
|
9月前
|
机器学习/深度学习 自然语言处理 算法
程序员的炫技代码写法
程序员的炫技代码写法
|
10月前
|
存储 编译器 C++
|
10月前
|
C++
【C++】如何写一个C++类?
【C++】如何写一个C++类?
57 0
|
设计模式 存储 安全
我终于读懂了单例模式。。。
我终于读懂了单例模式。。。
我终于读懂了单例模式。。。
|
存储 SQL 安全
深究JAVA反射机制
JAVA反射机制详解
92 0
深究JAVA反射机制
|
设计模式 安全 算法
单例模式的十种写法,你会几个?
单例模式是一种最常见的设计模式,写法也比较多,在这篇文章里面主要是对单例模式的各种写法进行一个介绍。面试的时候会对其中两三种进行体会,而且我还遇到了口述单例模式的例子。重要性就不言而喻了吧。
175 0
单例模式的十种写法,你会几个?