• Objective-C设计模式——单例Singleton(对象创建)


    单例

    和其它语言的单例产不多,可以说是最简单的一种设计模式了。但是有几个点需要注意下,单例就是一个类只有一个实例。

    所以我们要想办法阻止该类产生别的实例,一般语言中都会将构造函数写为private。但是OC中的函数并没有限定符,所以我们需要用一些小技巧来屏蔽这一点。

    应用场景

    类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法。

    这个唯一的实例只能通过类的子类化进行扩展,而且扩展的对象不会破坏客户端代码。

    注意

    1.OC中单例的实例变量要定义在.m文件

    2.OC中单例需要重载allocWithZone:和copyWithZone:方法来防止创建别的实例。

    3.单例创建要注意线程安全,不然就可能出现多个实例。

    注意问题将会在Demo中讲解

    Demo

    首先先来看一个最常规,的不严谨的单例实现:

    复制代码
    @implementation Singleton
    
    static Singleton *sharedInstance;
    
    -(Singleton *)sharedInstance
    {
        if(sharedInstance)
        {
            sharedInstance = [Singleton new];
        }
        return sharedInstance;
    }
    
    @end
    复制代码

    这看似好像是可以得到单例对象了,但是这可以说是单例的一种变形。绝不能说这就是单例,因为我们可以轻松地通过其他方式来创建对象。

    所以我们还要我修改allocWithZone:和copyWithZone:方法(alloc 和 copy 方法实际上就是调用这两个方法)

    复制代码
    -(id)copyWithZone:(NSZone *)zone
    {
        return [[self class] sharedInstance];
    }
    
    +(id)allocWithZone:(struct _NSZone *)zone
    {
        return [self sharedInstance];
    }
    复制代码

    可是这就出现另一个问题,在sharedInstance方法里面我们实际调用过allocWithZone:(new 调用 alloc),但是它的alloc被我们重写了,这就会出现错误。所以我们需要修改sharedInstance方法

    复制代码
    +(Singleton *)sharedInstance
    {
        if(sharedInstance)
        {
            sharedInstance = [[super allocWithZone:NULL] init];
        }
        return sharedInstance;
    }
    复制代码

    这样就可以顺利的返回单例了,而且无法通过其它方式产生实例对象。

    看似完美了实际还会有问题出现,因为现在是非线程安全的,可能存在同一时间创建多个实例的情况,所以修改如下

    复制代码
    +(instancetype)sharedInstance
    {
        static dispatch_once_t once;
        dispatch_once(&once, ^{
            sharedInstance = [[super allocWithZone:NULL] init];
        });
        return sharedInstance;
    }
    复制代码

    客户端代码如下:

    复制代码
            Singleton *singleton = [Singleton sharedInstance];
            Singleton *singleton2 = [[Singleton alloc] init];
            Singleton *singleton3 = [singleton copy];
     
            [singleton print];
            [singleton2 print];
            [singleton3 print];
    复制代码

    输出结果:

    2015-07-21 21:10:32.797 Singleton[42537:10347987] 0x7fff5fbff7a8
    2015-07-21 21:10:32.798 Singleton[42537:10347987] 0x7fff5fbff7a8
    2015-07-21 21:10:32.798 Singleton[42537:10347987] 0x7fff5fbff7a8

    可以看到内存都指向了同一地址。

  • 相关阅读:
    深入理解java虚拟机笔记Chapter12
    深入理解java虚拟机笔记Chapter11
    深入理解java虚拟机笔记Chapter8
    深入理解java虚拟机笔记Chapter7
    深入理解java虚拟机笔记补充-JVM常见参数设置
    深入理解java虚拟机笔记Chapter4
    深入理解java虚拟机笔记Chapter3-内存分配策略
    Java从Txt文本进行数据提取
    C语言-格式输入输出中“%d,%o,%x,%e,%f,%s,%p”
    嵌入式学习书籍
  • 原文地址:https://www.cnblogs.com/pb89/p/4708785.html
Copyright © 2020-2023  润新知