• iOS开发之单例模式


    什么是单例 ?

    单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

    iOS开发中如何使用单例?

    传统的单例构造方法

    + (id)sharedInstance {

    static id sharedInstance;

    if(sharedInstance == nil){

    sharedInstance = [[]self alloc] init]

    }

    return sharedInstance;

    }

    多线程下的隐患 在多线程的情况下,如果两个线程几乎同时调用sharedInstance()方法会发生什么呢?

    有可能会创建出两个该类的实例。

    为了防止这种情况 我们通常会加上锁

    + (id)sharedInstance {

    static id sharedInstance;

    @synchronized(self)

    if(sharedInstance == nil)

    { sharedInstance = [[]self alloc] init]

    } }

    return sharedInstance;

    }

    dispatch_once iOS 4.0 引进了 GCD ,其中的 **dispatchonce**,它即使是在多线程环境中也能安全地工作,非常安全。dispatchonce是用来确保指定的任务将在应用的生命周期期间,仅执行一次。以下是一个典型的源代码以初始化的东西。它可以优雅通过使用dispatch_once来创建一个单例。

    + (id)sharedInstance {

    static dispatch_once_t once;

    static id sharedInstance;

    dispatch_once(&once, ^{ sharedInstance = [[self alloc] init]; }); return sharedInstance; }

    以下详谈dispatch_once创建单例

    利用dispatch_once创建单例

     
     无论是爱还是恨,你都需要单例。实际上每个iOS或Mac OS应用都至少会有UIApplicationNSApplication.
    什么是单例呢?Wikipedia是如此定义的:
    在软件工程中,单例是一种用于实现单例的数学概念,即将类的实例化限制成仅一个对象的设计模式。
    或者我的理解是:
    单例是一种类,该类只能实例化一个对象。
        尽管这是单例的实际定义,但在Foundation框架中不一定是这样。比如NSFileMangerNSNotificationCenter,分别通过它们的类方法defaultManagerdefaultCenter获取。尽管不是严格意义的单例,这些类方法返回一个可以在应用的所有代码中访问到的类的共享实例。在本文中我们也会采用该方法。
        使用Objective-C实现单例模式的最佳方式向来有很多争论,开发者(包括Apple在内)似乎每几年就会改变他们的想法。当Apple引入了Grand Central Dispatch (GCD)(Mac OS 10.6和iOS4.0),他们也引入了一个很适合用于实现单例模式的函数。
        该函数就是dispatch_once
    void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);
        该函数接收一个dispatch_once用于检查该代码块是否已经被调度的谓词(是一个长整型,实际上作为BOOL使用)。它还接收一个希望在应用的生命周期内仅被调度一次的代码块,对于本例就用于shared实例的实例化。
    dispatch_once不仅意味着代码仅会被运行一次,而且还是线程安全的,这就意味着你不需要使用诸如@synchronized之类的来防止使用多个线程或者队列时不同步的问题。
        Apple的GCD Documentation证实了这一点:
    如果被多个线程调用,该函数会同步等等直至代码块完成。
        实际要如何使用这些呢?
        好吧,假设有一个AccountManager类,你想在整个应用中访问该类的共享实例。你可以按如下代码简单实现一个类方法:
    + (AccountManager *)sharedManager { 
        static AccountManager *sharedAccountManagerInstance = nil; 

        static dispatch_once_t predicate; dispatch_once(&predicate, ^{       
              sharedAccountManagerInstance = [[self alloc] init]; 
        });

        return sharedAccountManagerInstance; 

    }
        这就意味着你任何时候访问共享实例,需要做的仅是:
    AccountManager *accountManager = [AccountManager sharedManager];
        就这些,你现在在应用中就有一个共享的实例,该实例只会被创建一次。
        该方法有很多优势: 
               1 线程安全
               2 很好满足静态分析器要求
               3 和自动引用计数(ARC)兼容 
               4 仅需要少量代码
        该方法的劣势就是它仍然运行创建一个非共享的实例:
    AccountManager *accountManager = [[AccountManager alloc] init];
        有些时候你希望有这种行为,但如果正在想要的是仅一个实例被实例化就需要注意这点。
     
     
  • 相关阅读:
    Java知识点梳理——集合
    Java知识点梳理——装箱和拆箱
    Shiro RememberMe 1.2.4 反序列化漏洞详细复现
    哈希长度拓展攻击之De1CTF
    Discuz! ML RCE漏洞 getshell 复现
    Redis基于主从复制的RCE 4.x/5.x 复现
    WebLogic反序列化漏洞(CVE-2019-2725补丁绕过)
    【实战2】记一次获取远程桌面历程
    远程桌面远程代码执行漏洞(CVE-2019-0708)Poc
    【实战1】记一次提至administrator权限历程
  • 原文地址:https://www.cnblogs.com/qyfeng009/p/5046506.html
Copyright © 2020-2023  润新知