zoukankan      html  css  js  c++  java
  • (转)ObjectiveC的单例模式(singleton)

    (转自: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
  • 相关阅读:
    太白老师 day06 编码 encode decode
    太白老师day6 1.代码块 2.is==id 3.小数据池
    MySQL 基本语法(1.表字段操作,2表记录管理 3.运算符管理4.SQL查询 5.约束6.索引
    List 接口常用子类及其特点
    Java 集合框架
    Java 常用工具类之基本对象包装类
    Java 常用工具类之 String 类
    Java 多线程间通信
    Java 多线程通信之多生产者/多消费者
    Java 之多线程通信(等待/唤醒)
  • 原文地址:https://www.cnblogs.com/xiaouisme/p/2340470.html
Copyright © 2011-2022 走看看