zoukankan      html  css  js  c++  java
  • iOS开发-单例模式

    单例模式是一种非常常见的设计模式,之前文章中UIApplication就是一种典型的单例模式,单例理解起来叶很简单,就不是不管如果访问始终只有一个实例化对象,定义全局共享的变量,如果对象是空则初始化一个对象,如果对象已经存在则使用已经实例化的对象。单例设计模式的作用是使得这个类的一个对象成为系统中的唯一实例,因此需要用一种唯一的方法去创建这个对象并返回这个对象的地址。下面有一张苹果官网的图片可以参考一下:

    定义一个Food类,大家共享同一个食物,定义一个静态变量,一个实例方法:

    static Food *sharedFoodObj=nil;
    
    +(Food *)sharedFood{
        if (!sharedFoodObj) {
            sharedFoodObj=[[Food alloc]init];
        }
        return sharedFoodObj;
    }
    

     执行以下代码,最后发现两个实例对象food和foodNext地址是一样的: 

     Food  *food=[Food sharedFood];
        Food  *foodNext=[Food sharedFood];
        NSLog(@"共享地址:%p-共享地址:%p",food,foodNext);
    

     如果每次都遵守规则调用sharedFood方法,单例模式算是完成了,但是对象是可以实例化的,看一段下面的代码:

        Food  *food=[Food sharedFood];
        Food  *foodInit=[[Food alloc]init];
        NSLog(@"共享地址:%p-实例地址:%p",food,foodInit);
    

     food和foodInit的地址是不一样,这个时候我们需要动手改造以下改成的方法,让实例化对象的出来的地址也是一样的,这个时候需要重写allocWithZone方法:

    +(Food *)sharedFood{
        if (!sharedFoodObj) {
            sharedFoodObj=[[super allocWithZone:NULL]init];
        }
        return sharedFoodObj;
    }
    
    +(instancetype)allocWithZone:(struct _NSZone *)zone{
        return [self sharedFood];
    }
    

     如果对象拷贝的时候也需要是同一对象的话,可以加一个方法:

    +(id)copyWithZone:(struct _NSZone *)zone{
        return [self sharedFood];
    }
    

    如果为了确保多线程情况下,仍然确保实体的唯一性,这个时候可以加上@synchronized,@synchronized的作用是创建一个互斥锁,保证此时没有其它线程对self对象进行修改。这个是objective-c的一个锁定令牌,防止self对象在同一时间内被其它线程访问,起到线程的保护作用。单例模式或者操作类的static变量中使用比较多。当两个并发线程访问同一个对象@synchronized(self)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

    +(Food *)sharedFood{
        @synchronized(self){
            if (!sharedFoodObj) {
                sharedFoodObj=[[Food alloc]init];
            }
        }
        return sharedFoodObj;
    }
    

     苹果Mac OS 10.6和iOS4.0后引入了GCD,利用GCD(Grand Central Dispatch)和ARC(Automatic Reference Counting)实现单例,这个时候我们可以通过dispatch_once简单的实现,代码如下:

    + (instancetype)sharedInstance
    {
        static Food *sharedFoodObj = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedFoodObj =[[super allocWithZone:NULL]init];
        });
        
        return sharedFoodObj;
    }
    

    Food.m中的代码:

    //
    //  Food.m
    //  Demo
    //http://www.cnblogs.com/xiaofeixiang
    //  Created by keso on 15/2/8.
    //  Copyright (c) 2015年 keso. All rights reserved.
    //
    
    #import "Food.h"
    
    @implementation Food
    
    static Food *sharedFoodObj=nil;
    
    
    
    +(Food *)sharedFood{
        if (!sharedFoodObj) {
            sharedFoodObj=[[super allocWithZone:NULL]init];
        }
        return sharedFoodObj;
    }
    
    
    //
    +(id)copyWithZone:(struct _NSZone *)zone{
        return [self sharedFood];
    }
    
    
    - (id)copyWithZone:(NSZone *)zone
    {
        return self;
    }
    
    
    
    + (instancetype)sharedInstance
    {
        static Food *sharedFoodObj = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedFoodObj =[[super allocWithZone:NULL]init];
        });
        
        return sharedFoodObj;
    }
    
    +(instancetype)allocWithZone:(struct _NSZone *)zone{
        return [self sharedInstance];
    }
    
    
    
    @end
    

     iOS的单例通过以上方式可以实现,网上有些文章实现单例用了七个方法,不过自从有了ARC之后,有些方法Apple已经不需要重写,说一个题外话,昨天有个博客园的园友只字不改抄袭了我的文章,文章下面说明栏也说明过了(博客经个人辛苦努力所得,如有转载会特别申明,博客不求技惊四座,但求与有缘人分享个人学习知识,生活学习提高之用),本人是自己辛苦所得,抄袭转载麻烦留一个链接,技术文章技术人看,做一个技术人需要有些底线~

  • 相关阅读:
    Kubernetes集群管理工具kubectl命令技巧大全
    LVM 逻辑卷扩容
    制作 Ubuntu 16.04 离线apt源
    Kubernetes 存储简介
    处理K8S PVC删除后pod报错
    处理 K8S Orphaned pod found
    Kubernetes之GlusterFS集群文件系统高可用安装,提供动态卷存储
    Linux安装MYSQL并部署主从复制集群
    CentOS 7.4通过rpm包离线安装 Mysql8.0并部署主从复制(附从库备份脚本)
    容器化安装Mysql 8.0 并部署主从复制
  • 原文地址:https://www.cnblogs.com/xiaofeixiang/p/4280182.html
Copyright © 2011-2022 走看看