单例模式(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单例

创建单例模式的五个步骤:

  1. 声明一个可以新建和获取单个实例对象的方法
  2. 声明一个static类型的类变量
  3. 声明一个只执行一次的任务
  4. 调用dispatch_once执行该任务指定的代码块,在该代码块中实例化上文声明的类变量
  5. 返回在整个应用的生命周期中只会被实例化一次的变量

下面用代码呈现:

//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];

}