单例模式(一)

作者: ef463f819996 | 来源:发表于2016-05-01 16:01 被阅读105次

单例是在整个项目中,一个类只能创建一个实例,而且方便供外界访问。所以实现单例模式最主要的就是要实现一个类只能创建一个实例。

以SpiderMan类为例子

1、类在创建实例的过程中,都会通过alloc来获取内存空间,要想类只能创建一个实例就必须得在alloc的时候控制类只创建一个实例。每次alloc的时候都会调用+ (id)allocWithZone:(struct _NSZone *)zone方法,多以应该在该方法中对实例进行处理。

首先需要一个全局外部变量 _instance,至于为什么要使用static,后面再说明。

static id _instance;

在allocWithZone:方法中创建这个实例

+ (id)allocWithZone:(struct _NSZone *)zone
{   
     if (_instance == nil) { // 防止创建多次
           _instance = [super allocWithZone:zone];
     }
     return _instance;
}

这样就基本上实现了一个类就只创建一个实例的功能。但是这并不完善,因为在多线程中,该类有可能创建不同的实例。所以为了保证该类只能创建一个实例还必须得考虑线程问题。所以为了解决该问题必须得给创建实例的代码加上一个线程锁,如:

+ (id)allocWithZone:(struct _NSZone *)zone
{
    @synchronized(self) {
        if (_instance == nil) { // 防止创建多次
            _instance = [super allocWithZone:zone];
        }
    }
    return _instance;
}

这样在线程上保证了单例性,但有点不足的是,每次创建实例的时候,都会重复地加锁,所以再做如下处理:

+ (id)allocWithZone:(struct _NSZone *)zone
{
    if (_instance == nil) { // 防止频繁加锁
        @synchronized(self) {
            if (_instance == nil) { // 防止创建多次
                _instance = [super allocWithZone:zone];
            }
        }
    }
    return _instance;
}

2、一般地为了方便创建实例都会提供一个类方法shareXXX,而一般不会通过alloc来创建实例,所以给SpiderMan添加一个类方法

+ (id)shanreSpiderMan
{
    if (_instance == nil) { // 防止频繁加锁
        @synchronized(self) {
            if (_instance == nil) { // 防止创建多次
                _instance = [[self alloc] init];
            }
        }
    }
    return _instance;
}

3、还需要考虑的一个问题就是:如果单实例通过copy来拷贝一个对象时,这时拷贝的对象是一个新的对象,SpiderMan有了两个不同的对象,这与初衷相悖,所以为了解决这个问题

- (id)copyWithZone:(NSZone *)zone
{
    return _instance;
}

此时,单例基本上已经实现了,使用时只需要通过调用类方法shareSpiderMan就可以获得单例对象了。

现在再来看看前面提到的一个问题:为什么使用static?首先这个static可以用来修饰函数,也可以用来修饰变量,在这里修饰的是变量。另外还需要知道的一点就是,全局变量是可以在整个项目当中使用的,比如在该SpiderMan类中的_instance全局变量,如果没有加static的话,它可以在别的类中被访问到,通过extern id _instance即可以访问得到并修改该_instance。而static修饰的全局变量是仅限于当前文件内部的,外部文件是访问不了的即使是使用extern也不能访问到。

OK,这样就实现了单例模式了,详细代码已上传到Github:https://github.com/Anchlate/Singleton-SpiderMan

完善部分请看下一篇单例模式(二)

相关文章

  • 【设计模式】单例模式

    单例模式 常用单例模式: 懒汉单例模式: 静态内部类单例模式: Android Application 中使用单例模式:

  • Android设计模式总结

    单例模式:饿汉单例模式://饿汉单例模式 懒汉单例模式: Double CheckLock(DCL)实现单例 Bu...

  • 2018-04-08php实战设计模式

    一、单例模式 单例模式是最经典的设计模式之一,到底什么是单例?单例模式适用场景是什么?单例模式如何设计?php中单...

  • JAVA多线程之线程安全的单例模式

    概念:java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。单例模式有一...

  • IOS单例模式的底层原理

    单例介绍 本文源码下载地址 1.什么是单例 说到单例首先要提到单例模式,因为单例模式是单例存在的目的 单例模式是一...

  • 设计模式 - 单例模式

    设计模式 - 单例模式 什么是单例模式 单例模式属于创建型模式,是设计模式中比较简单的模式。在单例模式中,单一的类...

  • OC - 单例模式

    导读: 一、什么是单例模式 二、单例的作用 三、常见的单例类 四、自定义单例类的方法 一、什么是单例模式 单例模式...

  • Swift 和 Objective-C 单例模式详解

    单例模式分为严格单例模式和不严格单例模式。单例模式要求一个类有一个实例,有公开接口可以访问这个实例。严格单例模式,...

  • 设计模式之一:单例模式

    摘要:设计模式之一:单例模式目录介绍1.单例模式介绍2.单例模式定义3.单例模式使用场景4.单例模式的实现方式 4...

  • 设计模式之单例模式详解

    设计模式之单例模式详解 单例模式写法大全,也许有你不知道的写法 导航 引言 什么是单例? 单例模式作用 单例模式的...

网友评论

  • Mr_yinwei:用 @synchronized这种方式不好吧!!!
    ef463f819996:@Mr_yinwei 确实,在二中以做修改

本文标题:单例模式(一)

本文链接:https://www.haomeiwen.com/subject/clokrttx.html