Objective-C中单例模式的实现【转】

简介:

单例模式在Cocoa和Cocoa Touch中非常常见。比如这两个,[UIApplication sharedApplication][NSApplication sharedApplication],大家应该都见过。但是我们应该如何在代码中实现一个单例模式呢?

如果你对苹果的文档很熟悉的话,你一定知道,在Cocoa Foundamentals Guide中有一段实现单例模式的示例代码。大致如下:

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            33
            34
            35
            36
            37
            38
            39
            40
            41
            42
            43
            44
            45
            46
            47
            48
            49
            50
            51
            52
            53
            
/* Singleton.h */
            #import <Foundation/Foundation.h>
            
            @interface Singleton : NSObject
            + (Singleton *)instance;
            @end
            
            /* Singleton.m */
            #import "Singleton.h"
            static Singleton *instance = nil;
            
            @implementation Singleton
            
            + (Singleton *)instance {
                if (!instance) {
                    instance = [[super allocWithZone:NULL] init];
                }
                return instance;
            }
            
            + (id)allocWithZone:(NSZone *)zone {
                return [self instance];
            }
            
            - (id)copyWithZone:(NSZone *)zone {
                return self;
            }
            
            - (id)init {
                if (instance) {
                    return instance;
                }
                self = [super init];
                return self;
            }
            
            - (id)retain {
                return self;
            }
            
            - (oneway void)release {
                // Do nothing
            }
            
            - (id)autorelease {
                return self;
            }
            
            - (NSUInteger)retainCount {
                return NSUIntegerMax;
            }
            
            @end
            

这是一种很标准的Singleton实现,中规中矩。不过这种实现并不是线程安全的。所以各路大神都各显神威,给出了多种单例模式的实现。

Matt Gallagher在博客中放出了一个Macro,用来实现单例模式。虽然是一个宏定义的代码,但是具体实现还是很清楚的。代码如下:

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            33
            34
            35
            36
            37
            38
            39
            40
            41
            42
            43
            44
            45
            46
            47
            48
            49
            50
            51
            52
            53
            54
            55
            56
            57
            58
            59
            60
            61
            62
            63
            64
            65
            66
            67
            68
            
//
            //  SynthesizeSingleton.h
            //  CocoaWithLove
            //
            //  Created by Matt Gallagher on 20/10/08.
            //  Copyright 2009 Matt Gallagher. All rights reserved.
            //
            //  Permission is given to use this source code file without charge in any
            //  project, commercial or otherwise, entirely at your risk, with the condition
            //  that any redistribution (in part or whole) of source code must retain
            //  this copyright and permission notice. Attribution in compiled projects is
            //  appreciated but not required.
            //
            
            #define SYNTHESIZE_SINGLETON_FOR_CLASS(classname) \
             \
            static classname *shared##classname = nil; \
             \
            + (classname *)shared##classname \
            { \
                @synchronized(self) \
                { \
                    if (shared##classname == nil) \
                    { \
                        shared##classname = [[self alloc] init]; \
                    } \
                } \
                 \
                return shared##classname; \
            } \
             \
            + (id)allocWithZone:(NSZone *)zone \
            { \
                @synchronized(self) \
                { \
                    if (shared##classname == nil) \
                    { \
                        shared##classname = [super allocWithZone:zone]; \
                        return shared##classname; \
                    } \
                } \
                 \
                return nil; \
            } \
             \
            - (id)copyWithZone:(NSZone *)zone \
            { \
                return self; \
            } \
             \
            - (id)retain \
            { \
                return self; \
            } \
             \
            - (NSUInteger)retainCount \
            { \
                return NSUIntegerMax; \
            } \
             \
            - (void)release \
            { \
            } \
             \
            - (id)autorelease \
            { \
                return self; \
            }
            

然而,eschaton则觉得这些实现都太繁琐了,他给出的实现如下:

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            33
            
@interface SomeManager : NSObject
            + (id)sharedManager;
            @end
            
            /* 非线程安全的实现 */
            @implementation SomeManager
            
            + (id)sharedManager {
                static id sharedManager = nil;
            
                if (sharedManager == nil) {
                    sharedManager = [[self alloc] init];
                }
            
                return sharedManager;
            }
            @end
            
            /* 线程安全的实现 */
            @implementation SomeManager
            
            static id sharedManager = nil;
            
            + (void)initialize {
                if (self == [SomeManager class]) {
                    sharedManager = [[self alloc] init];
                }
            }
            
            + (id)sharedManager {
                return sharedManager;
            }
            @end
            

关于为什么上述代码就能实现单例模式,以及关于线程安全问题的考量,请参考他的博客

最后介绍一个比较现代的单例模式实现。为什么说现代呢?因为这种实现利用了GCD(Grand Central Dispatch)和ARC(Automatic Reference Counting)。核心代码如下:

1
            2
            3
            4
            5
            6
            7
            8
            9
            
+ (id)sharedInstance
            {
              static dispatch_once_t pred = 0;
              __strong static id _sharedObject = nil;
              dispatch_once(&pred, ^{
                _sharedObject = [[self alloc] init]; // or some other init method
              });
              return _sharedObject;
            }
            

作者还写了一个宏(gist)来方便使用,大家可以阅读作者的博文A note on Objective-C singletons了解详情。

大多数情况下,Apple官方文档里的单例模式的示例代码实现已经够用了。虽然它最繁琐,但是也是本文介绍的几种单例模式中最容易理解的一个。至于其他的实现就留给读者们根据需要选择和应用了。

欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,转载请注明出处!














本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sunshine-anycall/archive/2012/05/31/2528650.html ,如需转载请自行联系原作者


相关文章
|
安全 iOS开发
Objective-c单例模式详解
单例模式出现以后,关于它的争执就一直存在。在开发项目中,有很多时候我们需要一个全局的对象,而且要保证全局有且仅有一份即可。没错,单例在这个时候就是最佳的选择,但是需要注意的是:在多线程的环境下也需要做好线程保护。其实系统已经有很多单例存在,例如UIApplication、NSNotification、NSFileManager等等就是很不错的例子——我们总有时候需要用到单例模式,不过写起代码来还是需要考量考量。
|
算法 数据安全/隐私保护 iOS开发
|
存储 缓存 iOS开发
深入Objective-C Runtime机制(一):类和对象的实现
1.概要      对于Runtime系统,相信大部分iOS开发工程师都有着或多或少的了解。对于Objective-C,Runtime系统是至关重要的,可以说是Runtime系统让Objective-C成为了区分于C语言,C++之外的一门独立开发语言,让OC在拥有了自己的面向对象的特性以及消息发送机制。并且因为其强大的消息发送机制,也让很多人认为Object
1953 0
|
存储 iOS开发
上古时代 Objective-C 中哈希表的实现
因为 ObjC 的 runtime 只能在 Mac OS 下才能编译,所以文章中的代码都是在 Mac OS,也就是 x86_64 架构下运行的,对于在 arm64 中运行的代码会特别说明。 写在前面 文章会介绍上古时代 Objective-C 哈希表,也就是 NXHashTable : NXHashTable 的实现 NXHashTable 的性
1340 0