iOS之单例模式常见写法
来源:互联网 发布:mysql update if 编辑:程序博客网 时间:2024/06/06 08:54
单例模式可能是设计模式中最简单的形式了,这一模式的意图就是使得类中的一个对象成为系统中的唯一实例。它提供了对类的对象所提供的资源的全局访问点。因此需要用一种只允许生成对象类的唯一实例的机制。下面让我们来看下单例的作用:
- 可以保证的程序运行过程,一个类只有一个示例,而且该实例易于供外界访问
- 从而方便地控制了实例个数,并节约系统资源。
单例模式的使用场合
- 类只能有一个实例,并且必须从一个为人数值的访问点对其访问。
- 这个唯一的实例只能通过子类化进行拓展,并且拓展的对象不会破坏客户端代码。
在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:方法,在这里创建唯一的实例(注意线程安全) + (instancetype)allocWithZone:(struct _NSZone *)zone{ @synchronized(self) { if (_instance == nil) { _instance = [super allocWithZone:zone]; } } return _instance;}
- 提供1个类方法让外界访问唯一的实例
+ (instancetype)sharedInstanceTool{ @synchronized(self){ if(_instance == nil){ _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.返回同一个实例。
方法二:
+(instancetype)sharedInstance { static WMSingleton *singleton = nil; if (! singleton) { singleton = [[self alloc] initPrivate]; } return singleton;}- (instancetype)init { @throw [NSException exceptionWithName:@"这个是个单例" reason:@"应该这样调用 [WMSingleton sharedInstance]" userInfo:nil]; return nil;}//实现自己真正的私有初始化方法- (instancetype)initPrivate { self = [super init]; return self;}
上面这段代码中将singleton指针声明为静态变量。当某个定义了静态变量的方法返回时,程序不会释放相应的变量。####singleton变量的初始值是nil,当程序第一次执行sharedInstance方法时会创建一个对象,并将新创建的对象的地址赋值给singleton变量。当徐成再次执行sharedInstance方法时,无论多少次singleton变量仍然会指向最初那个创建的对象。因为指向对象的singleton变量是强引用的,并且程序永远不会释放该变量,所以singleton变量指向的对象也不会释放。
线程安全。
上面的实例中我们通过@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 : NSObjectWMSingletonH(object)@end//.m类@implementation WMObjectWMSingletonM(Car)@end
通过上面的演练我们基本上学习了一些基本的单例模式然后在Cocoa Touch
框架中同样存在着大量的单例模式让我们来学习,比如UIApplication
、UIAccelerometer
、以及NSFileManager
等等。
0 0
- iOS之单例模式常见写法
- iOS开发之单例模式的写法
- 设计模式之单例模式的几种常见写法
- ios 单例模式的写法
- ios 单例模式 两种写法
- ios 单例模式的写法
- IOS 单例模式的写法
- iOS单例模式的官方写法
- iOS 单例模式的写法
- iOS 单例模式的写法
- iOS方法--------单例模式的写法
- iOS单例模式和单例的写法
- iOS 单例设计模式 单例写法
- C++中几种常见的单例模式写法。
- 单例模式的两种常见写法
- Java 单例模式 五种常见的写法
- 单例模式的三种常见写法
- 常见设计模式之【单例模式】
- HDU 4167 User Names
- 【二叉搜索数】HDU3791二叉搜索树
- SimplifyReader源码学习:(一)音乐播放功能总结
- Mac pro安装Ubuntu
- 2016SDAU编程练习三1012
- iOS之单例模式常见写法
- Android Service的Binder通信机制
- 大数相加 C/C++
- Okhttp session持久化
- Docker之常用命令
- LVDS接口详解
- 2016SDAU编程练习三1013
- super init
- 数据库学习之旅——实验3(1)