IOS中常用的设计模式

IOS中常用的设计模式

常用的设计模式有MVC、单例、KVO、工厂、策略等。注意有人认为KVC也是属于设计模式,其实KVC是属性赋值的方式,跟设计模式无关。

大家一般对MVC、单例、KVO、工厂比较熟悉,对策略稍有生疏。下面我给大家一一梳理一下,有不对的地方请大家指正。

MVC

模型-视图-控制器(Model-View-Controller,MVC)是Xerox PARC在20世纪80年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已广泛应用于用户交互应用程序中。在iOS开发中MVC的机制被使用的淋漓尽致,充分理解iOSMVC模式,有助于我们程序的组织合理性。

M 模型对象

模型对象封装了应用程序的数据,并定义操控和处理该数据的逻辑和运算。例如,模型对象可能是表示游戏中的角色或地址簿中的联系人。用户在视图层中所进行的创建或修改数据的操作,通过控制器对象传达出去,最终会创建或更新模型对象。模型对象更改时(例如通过网络连接接收到新数据),它通知控制器对象,控制器对象更新相应的视图对象。

V 视图对象

视图对象是应用程序中用户可以看见的对象。视图对象知道如何将自己绘制出来,并可能对用户的操作作出响应。视图对象的主要目的,就是显示来自应用程序模型对象的数据,并使该数据可被编辑。尽管如此,在 MVC 应用程序中,视图对象通常与模型对象分离。在iOS应用程序开发中,所有的控件、窗口等都继承自 UIView,对应MVC中的V。UIView及其子类主要负责UI的实现,而UIView所产生的事件都可以采用委托的方式,交给UIViewController实现。

C 控制器对象

在应用程序的一个或多个视图对象和一个或多个模型对象之间,控制器对象充当媒介。控制器对象因此是同步管道程序,通过它,视图对象了解模型对象的更改,反之亦然。控制器对象还可以为应用程序执行设置和协调任务,并管理其他对象的生命周期。控制器对象解释在视图对象中进行的用户操作,并将新的或更改过的数据传达给模型对象。模型对象更改时,一个控制器对象会将新的模型数据传达给视图对象,以便视图对象可以显示它。对于不同的UIView,有相应的UIViewController,对应MVC中的C。例如在iOS上常用的UITableView,它所对应的Controller就是UITableViewController。

MVC之间的关系:

1.Model和View永远不能相互通信,只能通过Controller传递。

2.Controller可以直接与Model对话(读写调用Model),Model通过Notification和KVO机制与Controller间接通信。

3.Controller可以直接与View对话,通过outlet,直接操作View,outlet直接对应到View中的控件,View通过action向Controller报告事件的发生(如用户Touch我了)。Controller是View的直接数据源(数据很可能是Controller从Model中取得并经过加工了)。Controller是View的代理(delegate),以同步View与Controller。


单例


首先看一下单例的例子:

/**

*          单例的写法常用的有三种方式:

方式1、不考虑线程

static SingleCase *manager = nil;

+ (SingleCase *)defaultManager {

if (!manager){

SingleCase = [[self alloc] init];

return manager;

}

}

方式2、考虑线程安全

+ (SingleCase *)sharedManager

{

static SingleCase *ManagerInstance = nil;

static dispatch_once_t predicate;

dispatch_once(&predicate, ^{

ManagerInstance = [[self alloc] init];

});

return ManagerInstance;

}

方式3、轻量级本地数据存储

NSUserDefaults *df = [NSUserDefaults standardUserDefaults];

//把auth 和uid写入本地

[df setObject:responseObject[M_Auth] forKey:M_Auth];

[df setObject:responseObject[M_Uid] forKey:M_Uid];

*/

IOS单例模式(singleton)

单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。

1.单例模式的要点:

显然单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。

2.单例模式的优点:

1.实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例。

2.灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程

IOS中的单例模式

在objective-c中要实现一个单例类,至少需要做以下四个步骤:

1、为单例对象实现一个静态实例,并初始化,然后设置成nil,

2、实现一个实例构造方法检查上面声明的静态实例是否为nil,如果是则新建并返回一个本类的实例,

3、重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不产生一个新实例,

4、适当实现allocWitheZone,copyWithZone,release和autorelease。

下面以SurveyRunTimeData为例子:

static SurveyRunTimeData *sharedObj = nil; //第一步:静态实例,并初始化。

@implementation SurveyRunTimeData

+ (SurveyRunTimeData*) sharedInstance  //第二步:实例构造检查静态实例是否为nil

{

@synchronized (self)

{

if (sharedObj == nil)

{

[[self alloc] init];

}

}

return sharedObj;

}

+ (id) allocWithZone:(NSZone *)zone //第三步:重写allocWithZone方法

{

@synchronized (self) {

if (sharedObj == nil) {

sharedObj = [super allocWithZone:zone];

return sharedObj;

}

}

return nil;

}

- (id) copyWithZone:(NSZone *)zone //第四步

{

return self;

}

- (id) retain

{

return self;

}

- (unsigned) retainCount

{

return UINT_MAX;

}

- (oneway void) release

{

}

- (id) autorelease

{

return self;

}

- (id)init

{

@synchronized(self) {

[super init];//往往放一些要初始化的变量.

return self;

}

}

@end


KVO


KVO  Key-Value Observing  键值观察者模式,提供一种机制,当指定的对象的属性被修改后,则监听者就会接受到通知。就好像我们给手机定了一个闹钟,等到了制定的时间,闹钟就会响起,我们就会知道时间到了。这个过程中,我们就是监听者,闹钟就是被监听的对象

我们创建一个student类,使用KVO模式,给其中的username 属性添加监听者(观察者 XSStudent*su = [[XSStudentalloc]init];    su.name= @"zhangsan";

su.age = 12;

//Observer 观察者是谁

//KeyPath监听的属性,比如监听学生的name属性

//options :监听的内容

//NSKeyValueObservingOptionNew,NSKeyValueObservingOptionOld这两个参数的意思是监听它的新值和旧值

[su addObserver:self forKeyPath:@"name"options:NSKeyValueObservingOptionNsw|NSKeyValueObservingOptionOld context:nil];

//修改属性,触发方法    su.name= @"lis";

//观察者观察到有值发生改变的时候发生的方法

- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context

{

//change  字典中的old  new  是关键字,专门用来存储新值和老值

NSLog(@"oldname %@",[changeobjectForKey:@"old"]);  

NSLog(@"new %@",[change objectForKey:@"new"]);

}

注意,这里(NSString*)keyPath 传过来的就是你添加观察者的时候创建的key  ,如果想要监听多个属性,你可以根据整个值来判断到底是哪个值的变化触发了该方法


工厂

一般是大批量生产零件的地方,在IOS中,工厂设计模式表示我们可以将一类控件提出来(使用静态方法),方便后期统一修改。其实这个也是大家常用的。如以下代码:

//定义工厂类,将常用的控件涉及到的属性用静态方法做一归纳总结,方便统一修改

//UIView

+ (UIView *)createViewWithFrame:(CGRect)frame;

//UILabel

+ (UILabel *)createLabelWithFrame:(CGRect)frame text:(NSString *)text textColor:(UIColor *)textColor backgroundColor:(UIColor *)backgroundColor font:(UIFont *)font textAlignment:(NSTextAlignment)textAlignment;

//UIButton

+ (UIButton *)createButtonWithFrame:(CGRect)frame title:(NSString *)title titleColor:(UIColor *)titleColor backgroundColor:(UIColor *)backgroundColor type:(UIButtonType)type target:(id)target  selector:(SEL)selector;

//UIImageView

+ (UIImageView *)createImageViewWithFrame:(CGRect)frame imageName:(NSString *)imageName;

//UITextField

+ (UITextField *)createTextFieldWithFrame:(CGRect)frame text:(NSString *)text placeholder:(NSString *)placeholder;


策略


同一个问题可以有多个解决办法,我们可以将这个多个解决办法封装成不同的方法,我们在使用的时候根据自己的需要选择合适的方法。选择其中一种方法,对其他的方法是没有影响的,我们把这个过程叫做策略设计模式。

这样可能还是不太好理解,我们举个例子,出行旅游:我们可以有几个策略可以考虑:可以骑自行车,汽车,做火车,飞机 ,当然你也可以选择步行。每个策略都可以得到相同的结果,但是它们使用了不同的资源。选择策略的依据是费用,时间,使用工具还有每种方式的方便程度 。

iOS应用分析

例如,我们在验证用户输入的表单的时候,加入包括电话输入框的验证和邮件输入框的验证,这两部分的验证算法是不同的,如果把这个算

法看成一个函数,他几乎有相同的输入参数和返回参数。我们可以把这个相同的函数可以抽象为基类(InputValidator)的一个方法(bool

validateInput(input,error)),然后抽象出两个具体的策略类:电话验证类(PhoneValidator)和邮件验证类

(EmailValidator),他们需要在各自的实现里面去复写父类的验证方法。为了能够正常的调用到验证类的验证方法,我们需要自定义一个

UITextField的子类CustomTextField,其中有一个InputValidator类型的引用和一个validate方法,该方法里

面调用InputValidator的验证方法,然后在textFieldDidEndEditing代理方法里面调用CustomTextField的

validate方法,这样就不用我们在判断输入是否合法的时候通过if else去处理每种逻辑,而且这样做方便扩展,提高可复用性。

今天先到这里,还要回去写程序,有空再来。

你可能感兴趣的:(IOS博客)