zoukankan      html  css  js  c++  java
  • B1-单例实现(单例宏)

    一、什么是单例

         单例就是,一个类,每次创建都是同一个对象。也就是说只能实例化一次。

    二、如何保证每次创建都是同一个对象

         创建一个对象归根揭底都会经过一个途径,alloc方法(alloc方法会调用allocWithZone:)。因此只要保证alloc方法只会调用一次,且保证线程安全,然后把此对象放在静态区。以后不管是创建对象还是copy对象都直接返回静态区的对象。

    三、注意点

         静态全局变量不需要考虑释放的问题(适用于MRC),解决线程安全问题可以用互斥锁或者GCD,后者更好。

         也可设置不让对象重复初始化,即让初始化方法只能执行一次。

    四、具体实现代码如下

    @implementation myManager
    static id instance;
    
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        // 1、互斥锁
    //        @synchronized (self) {
    //            if (instance == nil)
    //            {
    //                instance = [super allocWithZone:zone];
    //            }
    //        }
        
        // 2、GCD,只执行一次
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            if (instance == nil)
            {
                instance = [super allocWithZone:zone];
            }
        });
        return instance;
    }
    
    + (instancetype)sharedSoundTools
    {
        instance = [[self alloc] init];
        return instance;
    }
    
    - (id)copyWithZone:(NSZone *)zone
    {
        return instance;
    }
    
    #pragma mark - MRC 部分代码
    - (oneway void)release
    {
        // 什么都不做
    }
    
    - (instancetype)retain
    {
        // 本想什么都不做,但它要返回值
        return instance;
    }
    
    - (instancetype)autorelease
    {
        return instance;
    }
    
    - (NSUInteger)retainCount
    {
        // 此处防止有人不明就里的粗暴释放对象,比如while循环
        return ULONG_MAX;
    }
    
    - (instancetype)init
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            self = [super init];
            if (self)
            {
                self.age = 10; // 只是举个例子,只初始化一次,可以不设置
            }
        });
        return self;
    }
    
    @end

    五、单例宏

          以下代码写在单独singleton.h文件里,使用时直接包含.h头文件。

          使用方法,.h文件:singletonInterface(myManager);

                        .m文件:singletonImplementation(myManager);

          抽取代码如下:

    #define singletonInterface(className)          + (instancetype)shared##className;
    
    #if __has_feature(objc_arc)
    // 以下是ARC版本
    #define singletonImplementation(className) 
    + (instancetype)allocWithZone:(struct _NSZone *)zone { 
        static dispatch_once_t onceToken; 
        dispatch_once(&onceToken, ^{ 
            if (instance == nil) { 
                instance = [super allocWithZone:zone]; 
            } 
        }); 
        return instance; 
    } 
    + (instancetype)shared##className { 
        static dispatch_once_t onceToken; 
        dispatch_once(&onceToken, ^{ 
            instance = [[self alloc] init]; 
        }); 
        return instance; 
    } 
    - (id)copyWithZone:(NSZone *)zone { 
        return instance; 
    }
    #else
    // 以下是MRC版本
    #define singletonImplementation(className) 
    + (instancetype)allocWithZone:(struct _NSZone *)zone { 
        static dispatch_once_t onceToken; 
        dispatch_once(&onceToken, ^{ 
            if (instance == nil) { 
                instance = [super allocWithZone:zone]; 
            } 
        }); 
        return instance; 
    } 
    + (instancetype)shared##className { 
        static dispatch_once_t onceToken; 
            dispatch_once(&onceToken, ^{ 
            instance = [[self alloc] init]; 
        }); 
        return instance; 
    } 
    - (id)copyWithZone:(NSZone *)zone { 
        return instance; 
    } 
    - (oneway void)release {} 
    - (instancetype)retain {return instance;} 
    - (instancetype)autorelease {return instance;} 
    - (NSUInteger)retainCount {return ULONG_MAX;}
    #endif
    
    // 提示末尾一行不要有 

    六、单例的两种模式
         1、懒汉式,是在需要的时候再加载到内存。
         2、饿汉式,会在最早的时间就把单例创建好,放入内存,随时可以使用。

    // 饿汉式
    @implementation HMSoundTools
    static id instance;
    
    // 只要程序运行,就会执行一次
    + (void)load {
        instance = [[self alloc] init];
    }
    
    // 第一次用到类或者子类的时候,会执行一次
    //+ (void)initialize {
    //    
    //}
    
    + (instancetype)sharedSoundTools {
        return instance;
    }
    
    - (id)copyWithZone:(NSZone *)zone {
        return instance;
    }
     
     
  • 相关阅读:
    两种图像缩放算法的对比与实现
    字节流与字符流
    自己的网站 首都易搜网 又修改了一下。。首页改变了
    序列化和反序列化 .NET
    关于 C#异步方法的使用
    vs2010 设计视图中控件无法加载,提示未将对象设置到对象的实例。
    .Net 中的反射(查看基本类型信息) Part.2
    URL重写
    .Net 中的反射(序章) Part.1
    数据库死锁问题 及 解决方法
  • 原文地址:https://www.cnblogs.com/yaann/p/4216035.html
Copyright © 2011-2022 走看看