iOS开发——高级篇——iOS中常见的设计模式(MVC/单例/委托/观察者)
关于设计模式这个问题,在网上也找过一些资料,下面是我自己总结的,分享给大家
如果你刚接触设计模式,我们有好消息告诉你!首先,多亏了Cocoa的构建方式,你已经使用了许多的设计模式以及被鼓励的最佳实践。
首先得搞清楚设计模式是个什么鬼,在软件设计领域,设计模式是对通用问题的可复用的解决方案。设计模式是一系列帮你写出更可理解和复用代码的模板,设计模式帮你创建松耦合的代码以便你不需要费多大力就可以改变或者替换代码中的组件
其实iOS中的设计模式有非常多,常用的就下面这四种
一.MVC设计模式(设计模式之王)
MVC根据角色划分类,涉及到三个角色:
Model:模型保存应用程序的数据。
Controller:控制器是一个协调所有工作的中介者。它访问模型中的数据并在视图中展示它们,同时它们还监听事件和操作数据。
一个MVC模式的好的实现也就意味着每一个对象都会被划分到上面所说的组中。
我们可以很好的用下图来描述通过控制器实现的视图到模型的交互过程:

模型会把任何数据的变更通知控制器,然后控制器更新视图数据。视图对象通知控制器用户的操作,控制器要么根据需要来更新模型,要么检索任何被请求的数据。
你可能在想为什么不能仅仅使用控制器,在一个类中实现视图和模型,这样貌似更加容易?
所有的这些都归结于代码关注点分离以及复用。在理想的状态下,视图应该和模型完全的分离。如果视图不依赖某个实际的模型,那么视图就可以被复用来展示不同模型的数据。
举个例子来说,如果将来你打算加入电影或者书籍到你的资料库中,你仍然可以使用同样的AlbumView去显示电影和书籍数据。更进一步来说,如果你想创建一个新的与专辑有关联的工程,你可以很简单的复用Album类,因为它不依赖任何视图。这就是MVC的强大之处。
二.单例设计模式:
单例设计模式确保对于一个给定的类只有一个实例存在,这个实例有一个全局唯一的访问点。它通常采用懒加载的方式在第一次用到实例的时候再去创建它。
注意:苹果大量使用了此模式。例如:[NSUserDefaults standardUserDefaults], [UIApplication sharedApplication], [UIScreen mainScreen], [NSFileManager defaultManager],所有的这些方法都返回一个单例对象。
你很可能会想为什么这么关心是否一个类有多个实例?毕竟代码和内存都是廉价的,对吗?
有一些情况下,只有一个实例显得非常合理。举例来说,你不需要有多个Logger的实例,除非你想去写多个日志文件。或者一个全局的配置处理类:实现线程安全的方式访问共享实例是容易的,比如一个配置文件,有好多个类同时修改这个文件。
三、委托设计模式(Delegation)
这里先了解下其他两个设计模式,门面模式和装饰器模式,而委托则是装饰器模式中的经典实现;
门面模式:针对复杂的子系统提供了单一的接口,不需要暴漏一些列的类和API给用户,你仅仅暴漏一个简单统一的API。
装饰器(Decorator)模式:装饰器模式在不修改原来代码的情况下动态的给对象增加新的行为和职责,它通过一个对象包装被装饰对象的方法来修改类的行为,这种方法可以做为子类化的一种替代方法。
在Objective-C中,存在两种非常常见的实现:Category(类别)和Delegation(委托)
Category(类别):是一种不需要子类化就可以让你能动态的给已经存在的类增加方法的强有力的机制。新增的方法是在编译期增加的,这些方法执行的时候和被扩展的类的其它方法是一样的。它可能与装饰器设计模式的定义稍微有点不同,因为Category(类别)不会保存被扩展类的引用。
Delegation(委托):
委托作为另外一个装饰器模式,它是一种和其它对象交互的机制。举例来说,当你使用UITableView的时候,你必须要实现tableView:numberOfRowsInSection:方法。
你不可能让UITableView知道它需要在每个区域显示多少行,因为这些是应用特定的数据。因此计算每个区域需要显示多少行的职责就给了UITableView的委托。这就让UITableView类独立于它要显示的数据。
这里通过一个图来解释当你创建UITableView的时候会发生什么:
UITableView的职责就是显示一个表格视图。然而最终它需要一些它自身没有的信息。那么它就求助于它的委托,通过发送消息给委托来获取信息。在Objective-C实现委托模式的时候,一个类可以通过协议(Protocol)来声明可选以及必要的方法。
子类化一个对象,复写需要的方法看起来好像更容易一点,但是考虑到你只能子类化一个类,如果你想一个对象作为两个或者更多对象的委托的话,使用子类化将不能实现。
注意:这个是一个重要的模式。苹果在UIKit类中大量使用了它:UITableView, UITextView, UITextField, UIWebView, UIAlert, UIActionSheet, UICollectionView, UIPickerView,UIGestureRecognizer, UIScrollView等等等。
四、观察者模式
在观察者模式中,一个对象任何状态的变更都会通知另外的对改变感兴趣的对象。这些对象之间不需要知道彼此的存在,这其实是一种松耦合的设计。当某个属性变化的时候,我们通常使用这个模式去通知其它对象。
此模式的通用实现中,观察者注册自己感兴趣的其它对象的状态变更事件。当状态发生变化的时候,所有的观察者都会得到通知。苹果的推送通知(Push Notification)就是一个此模式的例子。
如果你要遵从MVC模式的概念,你需要让模型对象和视图对象在不相互直接引用的情况下通信。这正是观察者模式的用武之地。
Cocoa通过通知(Notifications)和Key-Value Observing(KVO)来实现观察者模式。
通知(Notifications):
不要和远程推送以及本地通知所混淆,通知是一种基于订阅-发布模式的模型,它让发布者可以给订阅者发送消息,并且发布者不需要对订阅者有任何的了解。
通知在苹果官方被大量的使用。举例来说,当键盘弹出或者隐藏的时候,系统会独立发送UIKeyboardWillShowNotification/UIKeyboardWillHideNotification通知。当你的应用进入后台运行的时候,系统会发送一个UIApplicationDidEnterBackgroundNotification通知。
KVO Key-Value Observing:
它是一种机制,当指定的对象的属性被修改后,KVO自动通知相应的观察者。
使用KVO的步骤
第一步:注册观察者[message addObserver:self forKeyPath:kKVOPathKey options:NSKeyValueObservingOptionNew context:Nil];
第二步:更改主题对象属性的值,即触发发送更改的通知 _message.key = @"asdfasd";
第三步:在制定的回调函数中,处理收到的更改通知
第四步:注销观察者 [_message removeObserver:self forKeyPath:kKVOPathKey];
iOS开发——高级篇——iOS中常见的设计模式(MVC/单例/委托/观察者)的更多相关文章
- iOS中常见的设计模式(MVC/单例/委托/观察者)
关于设计模式这个问题,在网上也找过一些资料,下面是我自己总结的,分享给大家 如果你刚接触设计模式,我们有好消息告诉你!首先,多亏了Cocoa的构建方式,你已经使用了许多的设计模式以及被鼓励的最佳实践. ...
- iOS开发——高级篇——iOS开发之网络安全密码学
一.非对称加密 - RSA : + 公钥加密,私钥解密: + 私钥加密,公钥解密: + 只能通过因式分解来破解 二.对称加密 - DES - 3DES - AES (高级密码标准,美国国家安全局使用, ...
- iOS开发——高级篇——iOS 项目的目录结构
最近闲来无事去面试一下iOS开发,让我感到吃惊的,面试官竟然问怎么分目录结构,还具体问每个子目录的文件名. 目录结构确实非常重要,面试官这么问,无疑是想窥探开发经验.清晰的目录结构,可让人一眼明白相应 ...
- iOS开发——高级篇——iOS中如何选择delegate、通知、KVO(以及三者的区别)
在开发IOS应用的时候,我们会经常遇到一个常见的问题:在不过分耦合的前提下,controllers[B]怎么进行通信.在IOS应用不断的出现三种模式来实现这种通信:1委托delegation2通知 ...
- iOS开发——高级篇——iOS中为什么block用copy属性
1. Block的声明和线程安全Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非ARC ...
- iOS开发——高级篇——iOS 中的 NSTimer
以前的老代码在使用 NSTimer 时出现了内存泄露 NSTimer fire 我们先用 NSTimer 来做个简单的计时器,每隔5秒钟在控制台输出 Fire .比较想当然的做法是这样的: 1 2 3 ...
- iOS开发——高级篇——iOS 强制退出程序APP代码
1.先po代码 UIAlertView* alert = [[UIAlertView alloc] initWithTitle:self.exitapplication message:@" ...
- iOS开发——高级篇——iOS如何彻底避免数组越界
我们先来看看有可能会出现的数组越界Crash的地方: ? 1 2 3 4 5 6 7 - (void)tableView:(UITableView *)tableView didSelectRowAt ...
- iOS开发——高级篇——iOS键盘的相关设置(UITextfield)
一.键盘风格 UIKit框架支持8种风格键盘. typedef enum { UIKeyboardTypeDefault, // 默认键盘:支持所有字符 UIKeyboardTypeASCIICapa ...
随机推荐
- java环境变量详细配置步骤
1 下载jdk. a 官网:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 本来 ...
- [译]React Context
欢迎各位指导与讨论 : ) 前言 由于笔者英语和技术水平有限,有不足的地方恳请各位指出.我会及时修正的 O(∩_∩)O 当前React版本 15.0.1 时间 2016/4/25 正文 React一个 ...
- linux解压包
1.命令格式:tar[必要参数][选择参数][文件] 2.命令功能:用来压缩和解压文件.tar本身不具有压缩功能.他是调用压缩功能实现的 3.命令参数:必要参数有如下:-A 新增压缩文件到已存在的压缩 ...
- c语言考前最后一天
明天就是考验这1个多月学习c语言的总结了,所以今天是个重要的日子,明天是个神圣的日子. 但是我还很多地方不明白,特别是函数,循环,这两个都是c语言最重要的,但我却没学好,上课还 时不时走神所以现在学的 ...
- iTextSharp生成pdf的一个简单例子
效果图: 参考:http://www.cnblogs.com/CareySon/archive/2011/11/09/2243496.html http://www.cnblogs.com/julyl ...
- Ext小总结
titleCollapse:true,//高级搜索点击隐藏显示 添加按钮 >弹出页面 1.添加按钮 //核销 在控制层页面添加页面路径>添加操作按钮>window.allOrder ...
- Visual Studio 2015 Pre Secondary Installer 在哪里
安装vs2015 pre后,会自动打开Secondary Installer, 用于Cross Platform的移动开发框架,包括Cordova插件.若安装失败,启动程序位置: "D:\P ...
- FPGA与simulink联合实时环路系列—开篇
FPGA与simulink联合实时环路系列—开篇 作为网络上第一个开源此技术,笔者迫不及待地想将此技术分享出来,希望大家多多支持.笔者从2011年接触FPGA以来,从各个方面使用FPGA,无论是控制. ...
- Hadoop之倒排索引
前言: 从IT跨度到DT,如今的数据每天都在海量的增长.面对如此巨大的数据,如何能让搜索引擎更好的工作呢?本文作为Hadoop系列的第二篇,将介绍分布式情况下搜索引擎的基础实现,即“倒排索引”. 1. ...
- miniui无法传递input值
miniui获取到的值死活传不到php去处理,input框里有值php接收到却一直为空,又是查资料.测试.搜索.提问,最后才在文档中发现尼玛miniui不用name的,其实是<input tex ...