Objective-C中的单例模式

简介:

 ​    ​单例模式算是设计模式中比较简单的一种吧,设计模式不是只针对某种编程语言,在C++, Java, PHP等其他OOP语言也有设计模式,笔者初接触设计模式是通过《漫谈设计模式》了解的。这本书中是用java写的,个人感觉拜读完这本书以后虽然有不理解的地方但还是收获蛮大的。上面提到依赖注入,控制翻转的时候,没大看懂,当学习到Strut,Spring, Hibernate的东西的时候才略懂略懂。不过在23种设计模式里面单例模式还是算比较好理解的, 那么在OC中又是怎么来表示单例模式的呢?下面会结合着lusashi的代码,理解一下OC中得单例模式。

    ​    ​首先得了解什么是单例模式,用大白话说,单例模式就是在程序中这个类只对应着一个实例,这就是单例模式,单例模式一般用全局静态对象来实现。下面我们会建立一个生成单例的类SingletonClass,在实现文件中定义各种方法来实现我们的单例模式。

 

    ​    ​1.单例模式一般用全局静态对象来实现,所以我们在SingletonClass.m中定义一个静态全局变量是少不了的

//定义静态全局变量
static SingletonClass *single = nil;


    ​    ​2.上面的静态变量是定义在实现文件中的所以是私有的,要想获取该类的实例得有个getInstance方法来获取实例,在给静态变量分配内存空间之前首先要判断是否已经分配过啦,确保单例,如果分配过了就不分配了。
//获取静态全局对象
+(id)getInstance
{
    //如果没有生成对象,则为静态全局变量分配内存
    if (single == nil) {
        single = [[SingletonClass alloc] init];
    }
    return single;
}

    ​    ​

    ​    ​3.为了防止用户通过alloc和new来实例化对象,因此我们要对类方法allcoWithZone进行重写

//防止通过alloc或者new来创建新的对象我们要重写allocWithZone
+(id)allocWithZone:(NSZone *)zone
{
    if (single == nil) {
        single = [[super allocWithZone:zone] init];
    }
    return single;
}

 

    ​    ​4.为了防止用户把单例进行深浅拷贝,我们需要重写copyWithZone方法和mutableCopyWithZone方法,在重写方法之前我们的单例类必须遵循协议NSCoping和NSMutableCoping协议

    ​    ​遵循协议代码如下:

@interface SingletonClass : NSObject<NSCopying, NSMutableCopying>
 
//单例中获取单例对象的方法
+(id) getInstance;
 
//单例测试方法
-(void) singletonFunction;
 
@end

 

    ​    ​重写copyWithZone方法

//为了防止通过copy来创建新的实例我们要重写copyWithZone;
-(id)copyWithZone:(NSZone *)zone
{
    return self;
}

 

    ​    ​重写mutableCopyWithZone方法

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

 

    ​5.防止用户把创建的单例dealloc,我们需要重写retainCount方法

//重写retainCount方法,防止被dealloc,返回最大值
-(NSUInteger) retainCount
{
    return NSUIntegerMax;
}

 

    ​6. 重写release,autorelease, retain方法

//重写retain,引用计数不变
-(id) retain
{
    return self;
}
 
//重写release
-(oneway void) release
{
}
 
//重写autorelease
-(id) autorelease
{
    return self;
}

 

    ​至此我们的单例模式基本创建完毕,下面开始我们的测试吧;

    ​在main函数中的代码如下:

//单例模式的测试
SingletonClass *single1 = [SingletonClass getInstance];
SingletonClass *single2 = [SingletonClass new];
SingletonClass *single3 = [[SingletonClass alloc] init];
SingletonClass *single4 = [single1 copy];
SingletonClass *single5 = [single1 mutableCopy];
SingletonClass *single6 = [single1 retain];
[single1 release];
 
[single1 singletonFunction];
NSLog(@"single_retainCount = %lu", single1.retainCount);
 
//输出地址
NSLog(@"getInstance     single1_P = %p", single1);
NSLog(@"new             single2_P = %p", single2);
NSLog(@"allo            single3_P = %p", single3);
NSLog(@"copy            single4_P = %p", single4);
NSLog(@"mutableCopy     single5_P = %p", single5);
NSLog(@"retain          single6_P = %p", single6);

 

    ​    ​运行结果如下:

2014-08-07 16:04:44.207 Memory[20664:303] singleton Ps: 我是单例模式中得测试方法!!
2014-08-07 16:04:44.207 Memory[20664:303] single_retainCount = 18446744073709551615
2014-08-07 16:04:44.207 Memory[20664:303] getInstance     single1_P = 0x100204690
2014-08-07 16:04:44.208 Memory[20664:303] new             single2_P = 0x100204690
2014-08-07 16:04:44.208 Memory[20664:303] alloC            single3_P = 0x100204690
2014-08-07 16:04:44.208 Memory[20664:303] copy            single4_P = 0x100204690
2014-08-07 16:04:44.209 Memory[20664:303] mutableCopy     single5_P = 0x100204690
2014-08-07 16:04:44.209 Memory[20664:303] retain          single6_P = 0x100204690

​    ​    ​单例的地址是不变的。

     上面是在非ARC模式下得单例模式,那么在ARC模式下我们应如何实现我们的单例模式呢,我们下面就会给出ARC下的单例模式,用下面的方法,因没有重写alloc,copy等方法,通过alloc还是可以给该对象分配一个新对象的,上面是线程不安全的,下面是线程安全的:

+ (id)sharedSingleton {
    static MySingleton *sharedSingleton = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedSingleton = [[self alloc] init];
    });
    return sharedSingleton;
}

相关文章
|
安全 iOS开发
Objective-c单例模式详解
单例模式出现以后,关于它的争执就一直存在。在开发项目中,有很多时候我们需要一个全局的对象,而且要保证全局有且仅有一份即可。没错,单例在这个时候就是最佳的选择,但是需要注意的是:在多线程的环境下也需要做好线程保护。其实系统已经有很多单例存在,例如UIApplication、NSNotification、NSFileManager等等就是很不错的例子——我们总有时候需要用到单例模式,不过写起代码来还是需要考量考量。
|
6月前
|
安全 编译器 Swift
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
404 2
|
4月前
|
开发工具 iOS开发 容器
【Azure Blob】关闭Blob 匿名访问,iOS Objective-C SDK连接Storage Account报错
iOS Objective-C 应用连接Azure Storage时,若不关闭账号的匿名访问,程序能正常运行。但关闭匿名访问后,上传到容器时会出现错误:“Public access is not permitted”。解决方法是将创建容器时的公共访问类型从`AZSContainerPublicAccessTypeContainer`改为`AZSContainerPublicAccessTypeOff`,以确保通过授权请求访问。
【Azure Blob】关闭Blob 匿名访问,iOS Objective-C SDK连接Storage Account报错
|
6月前
|
缓存 开发工具 iOS开发
优化iOS中Objective-C代码调起支付流程的速度
优化iOS中Objective-C代码调起支付流程的速度
108 2
|
6月前
|
安全 JavaScript 前端开发
IOS开发基础知识:介绍一下 Swift 和 Objective-C,它们之间有什么区别?
IOS开发基础知识:介绍一下 Swift 和 Objective-C,它们之间有什么区别?
276 0
|
iOS开发 容器
iOS 代码规范格式 Objective-C(上)
iOS 代码规范格式 Objective-C
434 0
iOS 代码规范格式 Objective-C(上)
|
编译器 API iOS开发
iOS 代码规范格式 Objective-C(下)
iOS 代码规范格式 Objective-C(下)
238 0
|
机器学习/深度学习 API iOS开发
【IOS 开发】Objective-C Foundation 框架 -- 字符串 | 日期 | 对象复制 | NSArray | NSSet | NSDictionary | 谓词(一)
【IOS 开发】Objective-C Foundation 框架 -- 字符串 | 日期 | 对象复制 | NSArray | NSSet | NSDictionary | 谓词(一)
178 0