您的位置:首页 > 移动开发 > Objective-C

(转)Objective-C的单例模式(singleton)

2012-02-06 17:47 274 查看
(转自:http://blog.csdn.net/arthurchenjs/article/details/6699598)

如果你准备写一个类,希望保证只有一个实例存在,同时可以得到这个特定实例提供服务的入口,那么可以使用单态设计模式。

单态模式在Java、C++中很常用,在Cocoa里,也可以实现。

但是,

Objective-C的单例模式绝对和你所想象不一样,他的写法和你所见过的所有语言的写法都不一样。

官方建议

由于自己设计单态模式存在一定风险,主要是考虑到可能在多线程情况下会出现的问题,因此苹果官方建议使用以下方式来实现单态模式:

static MyGizmoClass *sharedGizmoManager = nil;
+ (MyGizmoClass*)sharedManager
{
@synchronized(self) {
if (sharedGizmoManager == nil) {
[[self alloc] init]; // assignment not done here
}
}
return sharedGizmoManager;
}
+ (id)allocWithZone:(NSZone *)zone
{
@synchronized(self) {
if (sharedGizmoManager == nil) {
sharedGizmoManager = [super allocWithZone:zone];
return sharedGizmoManager; // assignment and return on first allocation
}
}
return nil; //on subsequent allocation attempts return nil
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain
{
return self;
}
- (unsigned)retainCount
{
return UINT_MAX; //denotes an object that cannot be released
}
- (void)release
{
//do nothing
}
- (id)autorelease
{
return self;
}

开源模板(附下载地址)

程序员都是偷懒的,现在流行使用一个宏定义来搞定这许多的事,而且考虑的更加周全。

单例包含以下接口

+ (MyClass*) sharedInstance;
+ (void) purgeSharedInstance;

调用sharedInstance会创建并返回单例

调用purgeSharedInstance会销毁单例

手动调用alloc也可以保证是单例,你可以这样调用

[[MyClass alloc] initWithParam:firstParam secondParam:secondParam];

只是要保证在sharedInstance之前调用,因为只有一次创建机会。

下面是使用宏的写法“

MyClass.h:
========================================
#import "SynthesizeSingleton.h"

@interface MyClass: SomeSuperclass
{
...
}
SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(MyClass);

@end
========================================

MyClass.m:
========================================
#import "MyClass.h"

@implementation MyClass

SYNTHESIZE_SINGLETON_FOR_CLASS(MyClass);

...

@end
========================================

下载地址

http://arthurchen.blog.51cto.com/attachment/201108/2483760_1313658868.rar

以上转载完毕。

----------------------------------分割线------------------------------------

以下是本人(xiaou)补充的:

上面下载地址下载下来的开源模板内容如下:(经本人在xcode4环境下验证修改了一两处compiled error)

文件名:SynthesizeSingleton.h

----------------------------------分割线------------------------------------

#ifndef SYNTHESIZE_SINGLETON_FOR_CLASS

#import <objc/runtime.h>

#pragma mark -
#pragma mark Singleton

/* Synthesize Singleton For Class
*
* Creates a singleton interface for the specified class with the following methods:
*
* + (MyClass*) sharedInstance;
* + (void) purgeSharedInstance;
*
* Calling sharedInstance will instantiate the class and swizzle some methods to ensure
* that only a single instance ever exists.
* Calling purgeSharedInstance will destroy the shared instance and return the swizzled
* methods to their former selves.
*
*
* Usage:
*
* MyClass.h:
* ========================================
*    #import "SynthesizeSingleton.h"
*
*    @interface MyClass: SomeSuperclass
*    {
*        ...
*    }
*    SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(MyClass);
*
*    @end
* ========================================
*
*
*    MyClass.m:
* ========================================
*    #import "MyClass.h"
*
*    @implementation MyClass
*
*    SYNTHESIZE_SINGLETON_FOR_CLASS(MyClass);
*
*    ...
*
*    @end
* ========================================
*
*
* Note: Calling alloc manually will also initialize the singleton, so you
* can call a more complex init routine to initialize the singleton like so:
*
* [[MyClass alloc] initWithParam:firstParam secondParam:secondParam];
*
* Just be sure to make such a call BEFORE you call "sharedInstance" in
* your program.
*/

#define SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(__CLASSNAME__)    \
\
+ (__CLASSNAME__*) sharedInstance;    \
+ (void) purgeSharedInstance;

#define SYNTHESIZE_SINGLETON_FOR_CLASS(__CLASSNAME__)    \
\
static __CLASSNAME__* volatile _##__CLASSNAME__##_sharedInstance = nil;    \
\
+ (__CLASSNAME__*) sharedInstanceNoSynch    \
{    \
return (__CLASSNAME__*) _##__CLASSNAME__##_sharedInstance;    \
}    \
\
+ (__CLASSNAME__*) sharedInstanceSynch    \
{    \
@synchronized(self)    \
{    \
if(nil == _##__CLASSNAME__##_sharedInstance)    \
{    \
_##__CLASSNAME__##_sharedInstance = [[self alloc] init];    \
}    \
else    \
{    \
NSAssert2(1==0, @"SynthesizeSingleton: %@ ERROR: +(%@ *)sharedInstance method did not get swizzled.", self, self);    \
}    \
}    \
return (__CLASSNAME__*) _##__CLASSNAME__##_sharedInstance;    \
}    \
\
+ (__CLASSNAME__*) sharedInstance    \
{    \
return [self sharedInstanceSynch]; \
}    \
\
+ (id)allocWithZone:(NSZone*) zone    \
{    \
@synchronized(self)    \
{    \
if (nil == _##__CLASSNAME__##_sharedInstance)    \
{    \
_##__CLASSNAME__##_sharedInstance = [super allocWithZone:zone];    \
if(nil != _##__CLASSNAME__##_sharedInstance)    \
{    \
Method newSharedInstanceMethod = class_getClassMethod(self, @selector(sharedInstanceNoSynch));    \
method_setImplementation(class_getClassMethod(self, @selector(sharedInstance)), method_getImplementation(newSharedInstanceMethod));    \
method_setImplementation(class_getInstanceMethod(self, @selector(retainCount)), class_getMethodImplementation(self, @selector(retainCountDoNothing)));    \
method_setImplementation(class_getInstanceMethod(self, @selector(release)), class_getMethodImplementation(self, @selector(releaseDoNothing)));    \
method_setImplementation(class_getInstanceMethod(self, @selector(autorelease)), class_getMethodImplementation(self, @selector(autoreleaseDoNothing)));    \
}    \
}    \
}    \
return _##__CLASSNAME__##_sharedInstance;    \
}    \
\
+ (void)purgeSharedInstance    \
{    \
@synchronized(self)    \
{    \
if(nil != _##__CLASSNAME__##_sharedInstance)    \
{    \
Method newSharedInstanceMethod = class_getClassMethod(self, @selector(sharedInstanceSynch));    \
method_setImplementation(class_getClassMethod(self, @selector(sharedInstance)), method_getImplementation(newSharedInstanceMethod));    \
method_setImplementation(class_getInstanceMethod(self, @selector(retainCount)), class_getMethodImplementation(self, @selector(retainCountDoSomething)));    \
method_setImplementation(class_getInstanceMethod(self, @selector(release)), class_getMethodImplementation(self, @selector(releaseDoSomething)));    \
method_setImplementation(class_getInstanceMethod(self, @selector(autorelease)), class_getMethodImplementation(self, @selector(autoreleaseDoSomething)));    \
[_##__CLASSNAME__##_sharedInstance release];    \
_##__CLASSNAME__##_sharedInstance = nil;    \
}    \
}    \
}    \
\
- (id)copyWithZone:(NSZone *)zone    \
{    \
return self;    \
}    \
\
- (id)retain    \
{    \
return self;    \
}    \
\
- (NSUInteger)retainCount    \
{    \
NSAssert1(1==0, @"SynthesizeSingleton: %@ ERROR: -(NSUInteger)retainCount method did not get swizzled.", self);    \
return NSUIntegerMax;    \
}    \
\
- (NSUInteger)retainCountDoNothing    \
{    \
return NSUIntegerMax;    \
}    \
- (NSUInteger)retainCountDoSomething    \
{    \
return [super retainCount];    \
}    \
\
- (oneway void)release    \
{    \
NSAssert1(1==0, @"SynthesizeSingleton: %@ ERROR: -(void)release method did not get swizzled.", self);    \
}    \
\
- (void)releaseDoNothing{}    \
\
- (void)releaseDoSomething    \
{    \
@synchronized(self)    \
{    \
[super release];    \
}    \
}    \
\
- (id)autorelease    \
{    \
NSAssert1(1==0, @"SynthesizeSingleton: %@ ERROR: -(id)autorelease method did not get swizzled.", self);    \
return self;    \
}    \
\
- (id)autoreleaseDoNothing    \
{    \
return self;    \
}    \
\
- (id)autoreleaseDoSomething    \
{    \
return [super autorelease];    \
}

#endif
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: