iOS之单例模式初探

单例模式可能是设计模式中最简单的形式了,这一模式的意图就是使得类中的一个对象成为系统中的唯一实例。它提供了对类的对象所提供的资源的全局访问点。因此需要用一种只允许生成对象类的唯一实例的机制。下面让我们来看下单例的作用:
  • 可以保证的程序运行过程,一个类只有一个示例,而且该实例易于供外界访问
  • 从而方便地控制了实例个数,并节约系统资源。
单例模式的使用场合
  • 类只能有一个实例,并且必须从一个为人数值的访问点对其访问。
  • 这个唯一的实例只能通过子类化进行拓展,并且拓展的对象不会破坏客户端代码。
在Objective-C中方法都是公有的,而且OC的语言本身是动态类型的,因此所有类都可以相互发送对方的消息。,并且Cocoa框架使用计数的内存管理方式来维护对象的内存中的生存期。
下面让我们看一下OC当中的单例模式的写法,首先单例模式在ARC\MRC环境下的写法有所不同,需要编写2套不同的代码
  • 可以用宏判断是否为ARC环境
    #if _has_feature(objc_arc)
    #else
    //MRC #endif
    单例模式- ARC -方法一
  • ARC中单例模式的实现
  • 在 .m中保留一个全局的static的实例
 static id _instance;
 //重写allocWithZone:方法,在这里创建唯一的实例(注意线程安全)
 +(id)allocWithZone:(struct _NSZone*)zone{ @synchronized(self){ if(_instance){ _instance = [super allocWithZone:zone]; } } } return _instance;
  • 提供1个类方法让外界访问唯一的实例
    + (instancetype)sharedInstanceTool{
    @synchronized(self){
        if(_instance){
            _instance = [[self alloc] init];
        }
    }
    return _instance; }
  • 实现copyWithZone:方法

      -(id)copyWithZone:(struct _NSZone *)zone{
      return _instance;
      }
    我们在sharedInstanceTool,首先检查类的唯一实例是否已经创建,如果就会创建实例并将其返回。而之所以调用super而不是self,是因为已经在self中重载了基本的对象分配的方法,需要借用父类的功能来帮助处理底层内存的分配。
    allocWithZone:(struct _NSZone*)zone方法中,只是返回从sharedInstanceTool方法返回的类实例。而同样的在Cocoa框架中调用allocWithZone:(struct _NSZone*)zone会分配内存,引用计数会设置为1,然后返回实例。同样的重写(id)copyWithZone:(struct _NSZone *)zone方法,也是为了保证不会返回实例的副本,而是返回self.返回同一个实例。
线程安全。
上面的实例中我们通过@synchronized来添加了一个互斥锁,以此来保证线程安全。而现在我们开始尝试用线程的方式来实现一个加单的单例。
static WMObject *_instance;

+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone]; }); return _instance; } + (instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[self alloc] init]; }); return _instance; } - (id)copyWithZone:(NSZone *)zone { return _instance; }
从上面的代码我们可以看到,实现的思路基本上也是一致的我们在sharedInstanceTool,首先检查类的唯一实例是否已经创建,如果就会创建实例并将其返回。而略有不同的地方就是我们这次通过dispatch_once_t来保证线程的安全性。至于dispatch_once_t的用法这里就一一赘述了,线程的相关教程都会有其相关的描述。
到了这里一个简单的单例模式基本实现完成了,那么我们可以尝试着把它封装到一个宏里,然后方便其以后的调用
创建一个WMSingleton.h
// .h文件
#define WMSingletonH(name) + (instancetype)shared##name;

// .m文件
#define WMSingletonM(name) \ static id _instance; \ \ + (instancetype)allocWithZone:(struct _NSZone *)zone \ { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ _instance = [super allocWithZone:zone]; \ }); \ 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; \ }
使用方法
//.h类
//引入这个宏文件
#import "WMSingleton.h"
@interface WMObject : NSObject WMSingletonH(object) @end //.m类 @implementation WMObject WMSingletonM(Car) @end
通过上面的演练我们基本上学习了一些基本的单例模式然后在Cocoa Touch框架中同样存在着大量的单例模式让我们来学习,比如UIApplicationUIAccelerometer、以及NSFileManager等等。所以在单例模式的学习上还是依旧的任重道远呀。。。

转载于:https://www.cnblogs.com/pb89/p/4783437.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值