zoukankan      html  css  js  c++  java
  • iOS单例模式(面试必考)

    ​# 单例模式(面试必考)

    1. 单例模式的作用

    • 可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问
    • 从而方便地控制了实例个数,并节约系统资源

    2. 单例模式的使用场合

    • 在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次)

    3. ARC中,单例模式的实现

    • 1.在.m中保留一个全局的static的实例
    static id _instance;
    
    • 2.重写allocWithZone:方法,在这里创建唯一的实例(注意线程安全)
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [super allocWithZone:zone];
        });
        return _instance;
    }
    
    • 3.提供1个类方法让外界访问唯一的实例
    + (instancetype)sharedInstance
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[self alloc] init];
        });
        return _instance;
    }
    
    • 4.实现copyWithZone:方法
    - (id)copyWithZone:(struct _NSZone *)zone
    {
        return _instance;
    }
    

    4.ARC中完整版(GCD)

    static id _instance;
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
    
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[super allocWithZone:zone] init]; // 记住这儿是super,不能用self
        });
    
        return _instance;
    }
    
    + (instancetype)sharedPerson
    {
    
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[self alloc] init];
        });
        return _instance;
    }
    
    // copyWithZone方法的前提是必须先有一个对象
    - (id)copyWithZone:(NSZone *)zone
    {
        return _instance;
    }
    
    
    • 在实际开发中,一个应用程序可能有多个对象是单例对象,此时我们应该把单例抽成一个宏放在一个单独的.h文件中,千万不能用继承
      • 其中表示此行跟下面一行是一起的
      • ## 表示后面是参数
      • 此时,注释只能在上面,在右边注释会报错的
    // .h文件中的声明
    #define SLInstanceH(name)  + (instancetype)shared##name;
    // .m文件的实现
    #define SLInstanceM(name) static id _instance; 
    
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[super allocWithZone:zone] init];
        });
        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;
    }
    
    • 使用宏的时候
    • 在.m文件中
    #import <Foundation/Foundation.h>
    #import "SLSharedInstance.h"  // 导入,定义了宏的.h文件
    
    @interface SLPerson : NSObject<NSCopying>
    SLInstanceH(Person)  // 传入单例的对象
    @end
    
    • 在.h文件中
    #import "SLPerson.h"
    
    @implementation SLPerson
    SLInstanceM(Person)
    @end
    

    5. 单例模式(常规做法,非GCD)

    • 一定要加互斥锁,不然会有线程安全问题
    #import "SLPerson.h"
    
    @implementation SLPerson
    static id _instance;
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        @synchronized(self){ // 一定要加互斥锁,不然会有线程安全问题
            if (_instance == nil) {
                _instance = [[super allocWithZone:zone] init];
            }
        }
        return _instance;
    }
    + (instancetype)sharedPerson
    {
        @synchronized(self){
            if (_instance == nil) {
                _instance = [[self alloc] init];
            }
        }
        return _instance;
    }
    
    // 要有对象才能进行copy
    - (id)copyWithZone:(NSZone *)zone
    {
        return _instance;
    }
    @end
    
  • 相关阅读:
    祝贺我的博客訪问量过万(訪问量:10260次)
    【LeetCode-面试算法经典-Java实现】【107-Binary Tree Level Order Traversal II(二叉树层序遍历II)】
    Hibernate之HQL检索(查询)方式
    使用Nexus搭建Maven仓库
    poj2151之概率DP
    《从零開始学Swift》学习笔记(Day 71)——Swift与C/C++混合编程之数据类型映射
    D3D 点列练习
    poj 1733 Parity game
    命令行參数
    高速乘法
  • 原文地址:https://www.cnblogs.com/coderAlin/p/4752248.html
Copyright © 2011-2022 走看看