zoukankan      html  css  js  c++  java
  • IOS-单例模式

    单例模式可以保证在程序运行的过程中,一个类只有一个实例方法,而且该实例易于供外界访问。例如,oc中的 UIApplication 可以通过 [UIApplication sharedApplication] 方法开速实例化一个UIApplication对象,而且在整个项目中仅实例化一份,即只有一个内存地址。

    单例模式可以分为两类:(1)懒汉式,第一次用到这个单例对象的时候,再创建;(2)饿汉式,一进入程序就创建一个单例对象。在实际上一般都是“懒汉式”的单例模式,因为当项目中的单例对象较多时,如果使用“饿汉式”​单例模式,会导致程序在一启动就加载单例对象,或许项目中的很多单例一开始更不用不到,这样就消耗了不必要的内存。所以,一般选取“懒汉式”的单例模式,这样在需要的时候,再创建单例对象。

    实现单例对象步骤可以归纳为:

    (1)提供全局变量;

    (2)重写allocWithZone方法,(这是alloc底层调用的方法)

    (3)提供类方法sharedClassName​(其中ClassName为对象的名称),方便其他开发人员快速调用。

    (4)重写copyWithZone方法。

    如果是非ARC环境,基于上述步骤还要重写retain、retainCount、autorelease和release方法。​

    实现单例对象可以采用两种方式:一种是互斥锁访问,一种是GCD实现。

    互斥锁实现单例模式:

    static id _instance;
    //这里的static修饰全局变量,使得全局变量的作用域仅限于当前文件内,保证安全​
    //重写allocWithZone方法
    + (instancetype)allocWithZone:(struct _NSZone *)zone{
    
        if (_instance == nil) {//保证只加一次锁,方式重复加锁
    
            @synchronized(self) {//加锁,多线程安全
    
                if (_instance == nil) {//防止创建多次
    
                    _instance = [super allocWithZone:zone];
                }
            }
        }
        return _instance;
    }
    //实现外部调用的shared方法
    + (instancetype)sharedMusicTool{
        if (_instance == nil) {
            @synchronized(self) {
                if (_instance == nil) {
                    _instance = [[self alloc] init];
                }
            }
        }
        return _instance;
    }
    //实现copyWithZone方法
    - (id)copyWithZone:(NSZone *)zone{
        return _instance;
    }
    //非ARC要实现
    - (oneway void)release{
    }
    
    - (instancetype)retain{
        return self;
    }
    - (NSUInteger)retainCount{
        return 1;
    }
    - (instancetype)autorelease{
        return self;
    }
    

    GCD实现单例模式:

    static id _instance;
    //这里的static修饰全局变量,使得全局变量的作用域仅限于当前文件内,保证安全​
    //重写allocWithZone方法
    + (instancetype)allocWithZone:(struct _NSZone *)zone{
    	static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{//代码仅被执行一次
            _instance = [super allocWithZone:zone];
        });          
        return _instance;
    }
    //实现外部调用的shared方法
    + (instancetype)sharedMusicTool{
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{//代码仅被执行一次
            _instance = [[self alloc] init];
        });   
        return _instance;
    }
    //实现copyWithZone方法
    - (id)copyWithZone:(NSZone *)zone{
        return _instance;
    }
    //非ARC要实现
    - (oneway void)release{
    }
    
    - (instancetype)retain{
        return self;
    }
    - (NSUInteger)retainCount{
        return 1;
    }
    - (instancetype)autorelease{
        return self;
    }

    每次实现都用这段代码实现单例对象时,代码重复率高,因此定义一个专门实现单例对象的宏,其他单例对象直接调用单例的宏定义即可,简化了代码。宏定义为:

    //.h文件
    #define XCSingleModelH(name) + (instancetype)shared##name;
    
    //.m文件
    //ARC环境
    #if __has_feature(objc_arc)
    //ARC环境
    #define XCSingleModelM(name) 
    static id _instance; 
    
    + (instancetype)allocWithZone:(struct _NSZone *)zone{ 
        static dispatch_once_t onceToken; 
        dispatch_once(&onceToken, ^{ 
            _instance = [super allocWithZone:zone]; 
        }); 
        return _instance; 
    } 
     
    + (instancetype)shared##name{ 
        static dispatch_once_t onceToken; 
        dispatch_once(&onceToken, ^{ 
            _instance = [[self alloc] init]; 
        }); 
        return _instance; 
    } 
     
    - (id)copyWithZone:(NSZone *)zone{ 
        return _instance; 
    }
    #else
    
    //MRC环境,非ARC环境
    #define XCSingleModelM(name) 
    static id _instance; 
     
    + (instancetype)allocWithZone:(struct _NSZone *)zone{ 
        static dispatch_once_t onceToken; 
        dispatch_once(&onceToken, ^{ 
            _instance = [super allocWithZone:zone]; 
        }); 
        return _instance; 
    } 
     
    + (instancetype)shared##name{ 
        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 self; 
    } 
     
    - (NSUInteger)retainCount{ 
        return 1; 
    } 
     
    - (instancetype)autorelease{ 
        return self; 
    }
    #endif

    当定义一个单例对象的时候,可以引入宏定义:

    .h文件:

    #import <Foundation/Foundation.h>
    #import "<span style="font-family: Arial, Helvetica, sans-serif;">SingleHod</span>.h"
    
    @interface ClassName : NSObject
    
    SingleHod(ClassName);
    
    @end
    .m文件:
    <pre name="code" class="objc">#import "ClassName.h"
    #import "SingleHod.h"
    
    @implementation ClassName
    
    SingleHod(ClassName);
    
    @end


    
    



    不积跬步,无以至千里;不积小流,无以成江海。
  • 相关阅读:
    Vue中关于路由传参query和params的区别
    网页从输入网址到渲染完成经历了哪些过程?
    http常见的状态码
    项目中遇到哪些难点,如何解决的
    vue双向绑定、Proxy、defineproperty
    Proxy相比于defineProperty的优势
    axios
    虚拟DOM
    vue、react、angular三大框架对比 && 与jQuery的对比
    DOS、DOS攻击、DDOS攻击、DRDOS攻击
  • 原文地址:https://www.cnblogs.com/xiaocai-ios/p/7779816.html
Copyright © 2011-2022 走看看