单例模式(Singleton)
概念:整个应用或系统只能有该类的一个实例
在iOS开发我们经常碰到只需要某类一个实例的情况,最常见的莫过于对硬件参数的访问类,比如UIAccelerometer.这个类可以帮助我们获得硬件在各个方向轴上的加速度,但是我们仅仅需要它的一个实例就够了,再多,只会浪费内存。
苹果大量使用了此模式。例如:[NSUserDefaults standardUserDefaults], [UIApplication sharedApplication], [UIScreen mainScreen], [NSFileManager defaultManager],所有的这些方法都返回一个单例对象。
- UIApplication类提供了 +sharedAPplication方法创建和获取UIApplication单例
- NSBundle类提供了 +mainBunle方法获取NSBundle单例
- NSFileManager类提供了 +defaultManager方法创建和获得NSFileManager单例。(PS:有些时候我们得放弃使用单例模式,使用-init方法去实现一个新的实例,比如使用委托时)
- NSNotificationCenter提供了 +defaultCenter方法创建和获取NSNotificationCenter单例(该类还遵循了另一个重要的设计模式:观察者模式)
- NSUserDefaults类提供了 +defaultUserDefaults方法去创建和获取NSUserDefaults单例
创建单例模式的五个步骤:
- 声明一个可以新建和获取单个实例对象的方法
- 声明一个static类型的类变量
- 声明一个只执行一次的任务
- 调用dispatch_once执行该任务指定的代码块,在该代码块中实例化上文声明的类变量
- 返回在整个应用的生命周期中只会被实例化一次的变量
下面用代码呈现:
//Singleton.h @interface Singleton : NSObject + (Singleton *)sharedSingleton; //1声明一个可以新建和获取单个实例对象的方法 @end /***************************************************************/ //Singleton.m #import "Singleton.h" @implementation Singleton static Singleton *sharedSingleton = nil;// 2声明一个static类型的类变量 + (Singleton *)sharedSingleton{ static dispatch_once_t once; //3声明一个只执行一次的任务 dispatch_once(&once,^{ sharedSingleton = [[self alloc] init];// 调用dispatch_once执行该任务指定的代码块,在该代码块中实例化上文声明的类变量 //dosometing }); return sharedSingleton;// 返回在整个应用的生命周期中只会被实例化一次的变量(不止调用一次,但是只实例化一次) }
实际运用:在iOS应用中实现分层的架构设计,即我们需要把数据持久层,业务逻辑层,和展示层分开。(PersistenceLayer、 BusinessLogiclayer 、 PresentationLayer)
根据MVC的设计模式,我们又可以把持久层细分为DAO层(放置访问数据对象的四类方法-增删改查)和Domain层(各种实体类,比如日期,文本内容等)(DAO:Data Access Object数据访问对象是一个面向对象的接口)
实现:封装一个单例,用于初始化路径,文件等
// NoteDAO.h #import <Foundation/Foundation.h> #import "Note.h" @interface NoteDAO : NSObject + (NoteDAO*)sharedInstance; //插入Note方法 -(int) create:(Note*)model; //删除Note方法 -(int) remove:(Note*)model; //修改Note方法 -(int) modify:(Note*)model; //查询所有数据方法 -(NSMutableArray*) findAll; //按照主键查询数据方法 -(Note*) findById:(Note*)model; @end // NoteDAO.m #import "NoteDAO.h" @interface NoteDAO() //声明NoteDAO扩展 //NoteDAO扩展中DateFormatter属性是私有的 @property (nonatomic,strong) NSDateFormatter *dateFormatter; // NoteDAO扩展中沙箱目录中属性列表文件路径是私有的(所以不放在.h文件中声明) @property (nonatomic,strong) NSString *plistFilePath; @end @implementation NoteDAO static NoteDAO *sharedSingleton = nil; + (NoteDAO *)sharedInstance { static dispatch_once_t once; dispatch_once(&once, ^{ sharedSingleton = [[self alloc] init]; //初始化沙箱目录中属性列表文件路径 sharedSingleton.plistFilePath = [sharedSingleton applicationDocumentsDirectoryFile]; //初始化DateFormatter sharedSingleton.dateFormatter = [[NSDateFormatter alloc] init]; [sharedSingleton.dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; //初始化属性列表文件 [sharedSingleton createEditableCopyOfDatabaseIfNeeded]; }); return sharedSingleton; } //初始化属性列表文件 - (void)createEditableCopyOfDatabaseIfNeeded { 。。。 } - (NSString *)applicationDocumentsDirectoryFile { } - (int)create:(Note *)model { 。。。 } -(NSMutableArray*) findAll{ }
在业务逻辑层使用这个单例
// NoteBL.m
#import "NoteBL.h" @implementation NoteBL //插入Note方法 -(NSMutableArray*) createNote:(Note*)model { NoteDAO *dao = [NoteDAO sharedInstance]; [dao create:model]; return [dao findAll]; }