iOS开发:设计模式那点事

                       

说起设计模式,感觉自己把握不了笔头,所以单拿出 iOS 开发中的几种常用设计模式谈一下。  

单例模式 (Singleton) 

概念:整个应用或系统只能有该类的一个实例  

iOS 开发我们经常碰到只需要某类一个实例的情况,最常见的莫过于对硬件参数的访问类,比如 UIAccelerometer. 这个类可以帮助我们获得硬件在各个方向轴上的加速度,但是我们仅仅需要它的一个实例就够了,再多,只会浪费内存。  

所以苹果提供了一个 UIAccelerometer 的实例化方法+ sharedAccelerometer, 从名字上我们也能看出此方法让整个应用共享一个 UIAccelerometer 实例( PSiOS 的开放中,我们往往能从方法名中就了解这个方法的作用),它内部的如何实现我们暂且不谈,先来看看还有哪些类同样使用了单例模式。  

● UIApplication 类提供了 + sharedAPplication 方法创建和获取 UIApplication 单例  

● NSBundle 类提供了 +mainBunle 方法获取 NSBundle 单例  

● NSFileManager 类提供了 + defaultManager 方法创建和获得 NSFileManager 单例。( PS :有些时候我们得放弃使用单例模式,使用- init 方法去实现一个新的实例,比如使用委托时)  

● NSNotificationCenter 提供了 + defaultCenter 方法创建和获取 NSNotificationCenter 单例( PS :该类还遵循了另一个重要的设计模式:观察者模式)  

● NSUserDefaults 类提供了 + defaultUserDefaults 方法去创建和获取 NSUserDefaults 单例  

等等,苹果的 SDK 中大量的遵循此设计模式,那么它的内部是如何实现的呢?  

首先给大家介绍一下 GCD 技术,是苹果针对于多核 CPU 的多任务解决方案。你不需要了解更多,只需要知道是一组基于 C 语言开发的 API GCD 提供了一个 dispatch_once 函数,这个函数的作用就是保证 block (代码块:暂时理解为一个跟函数相近的东西。)里的语句在整个应用的生命周期里只执行一次。  

OK ,接下来就给出一个使用了单例模式新建和获取实例的类模版,代码如下:

//Singleton.h

@interface Singleton : NSObject

+ (Singleton *)sharedSingleton; <1>

@end

/***************************************************************/

//Singleton.m

#import "Singleton.h"

@implementation Singleton

static Singleton *sharedSingleton = nil;<2>

+ (Singleton *)sharedSingleton{

 static dispatch_once_t once;<3>

 dispatch_once(&once,^{

 sharedSingleton = [[self alloc] init];<4>

 //dosometing

 });

 return sharedSingleton;<5>

}

上述代码中有 5 小步,解释如下:  

1. 声明一个可以新建和获取单个实例对象的方法  

2. 声明一个 static 类型的类变量  

3. 声明一个只执行一次的任务  

4. 调用 dispatch_once 执行该任务指定的代码块,在该代码块中实例化上文声明的类变量  

5. 返回在整个应用的生命周期中只会被实例化一次的变量  

OK ,这就是 iOS 开发中单例模式的机制,下面我们就看看如何在实际开发中使用此模式?( PS :为了尽可能的突出核心内容,我们会对设计中的其他模式或内容一笔带过)  

假如我们需要在 iOS 应用中实现分层的架构设计,即我们需要把 数据 的持久层,展示层,和逻辑层分开。为了突出重点,我们直接把目光转到持久层,而根据 MVC 的设计模式,我们又可以把持久层细分为 DAO 层(放置访问数据对象的四类方法)和 Domain 层(各种实体类,比如学生),这样就可以使用 DAO 层中的方法,配合实体类 Domain 层对数据进行清晰的增删改查。那么我们如何设计呢?

从使用者的角度看,我们期望获得 DAO 层的类实例,然后调用它的增删改查四大方法。可是这个类实例,我们似乎只需要一个就足够了,再多的话不利于管理且浪费内存。 OK ,我们可以使用单例模式了,代码如下:  

.h 文件:

//StudentDAO.h

@interface StudentDAO:NSObject

@property (nonatomic,strong) NSMutaleArray *StudentsInfo;

+ (StudentDAO *)sharedStudentDAO;

-(int) create:(Student*)student;

-(int) remove:(Student*)student;

-(int) modify:(Student*)student;

-(NSMutaleArray) findAll;

@end

.m 文件:  

//StudentDAO.m

#import "StudentDAO.h"

#import "Student.h"

@implementation StudentDAO

static StudentDAO *studentDao = nil;

+ (StudentDAO)sharedStudentDAO{

 static dispatch_once_t once;

 dispatch_once(&once,^{

 Student *student1 = [[Student alloc]init];

 student1.name = "MexiQQ";

 student1.studentNum = "201200301101";

 Student *student2 = [[Student alloc]init];

 student2.name = "Ricardo_LI";

 student2.studentNum = "201200301102";

 studentDao = [[self alloc] init];

 studentDao._StudentsInfo = [[NSMutaleArray alloc]init];

 [studentDao._StudentsInfo addObject:student1];

 [studentDao._StudentsInfo addObject:student2];

 });

 return studentDao;

}

// 插入的方法

-(int)create:(Student*)stu{

 [self._StudentsInfo addObject:stu];

 return 0;

}

// 删除的方法

-(int)remove:(Student*)stu{

 for(Student* s in self._StudentsInfo){

 if([stu.studentNum isEqual:s.studentNum]){

 [self._StudentsInfo removeObject:s]

 break;

 }

 }

}

-(int)modify...... // 省略不写

-(NSMutaleArray)findAll...... // 省略不写

上述例子不难理解,其中用到的 Student 类我这里就不给出了,只是一个含有姓名和学号属性的实体类。  

观察者模式  

概念:一个对象状态改变,通知正在对他进行观察的对象,这些对象根据各自要求做出相应的改变  

图例:

 

如图所示:操作对象向被观察者对象投送消息,使得被观察者的状态得以改变,在此之前已经有观察者向被观察对象注册,订阅它的广播,现在被观察对象将自己状态发生改变的消息广播出来,观察者接收到消息各自做出应变。  

OK ,我们先来看看在苹果的 Cocoa Touch 框架中有谁使用了观察者模式:

通知 (notification) 机制  

原理图如下:

 

 

如图所示,在通知机制中对某个通知感兴趣的所有对象都可以成为接受者。首先,这些对象需要向通知中心( NSNotificationCenter )发出 addObserver:selector:name:object: 消息进行注册,在投送对象投送通知送给通知中心时,通知中心就会把通知广播给注册过的接受者。所有的接受者不知道通知是谁投送的,不去关心它的细节。投送对象和接受者是一对多的关系。接受者如果对通知不再关注,会给通知中心发送 removeObserver:name:Object: 消息解除注册,以后不再接受通知。  

ps: 这段话内容摘抄自关东升先生的文章)  

OK ,我们试着去使用一下通知机制:  

新建一个 Single view Project, 对项目中的文件做以下修改:  

AppDelegate.m 

- (void)applicationDidEnterBackground:(UIApplication *)application {

 [[NSNotificationCenter defaultCenter]postNotificationName:@"APPTerminate" object:self];

更多精彩内容,请关注 互联网分析沙龙微信:techxue   每天为您推送最新、最热干货!

                       

随意打赏

  • 评论
提交建议
微信扫一扫,分享给好友吧。