)Objective-C的單例模式(singleton)

來源:互聯網
上載者:User

(轉自: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
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.