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 ...
随机推荐
- 简单CSS3实现炫酷读者墙
如题,给大家介绍和讲解几个常用的CSS3属性,并用到实处. 先看demo(请使用Chrome或者Firefox浏览,IE的靠边): 点此查看实例 觉得爽的可以继续阅读下面的知识点,感觉不爽的可绕行. ...
- linq distinct 不够用了!
问题引出:在实际中遇到一个问题,要进行集合去重,集合内存储的是引用类型,需要根据id进行去重.这个时候linq 的distinct 就不够用了,对于引用类型,它直接比较地址.测试数据如下: class ...
- 让Web API支持Protocol Buffers
简介 现在我们Web API项目基本上都是使用的Json作为通信的格式,随着移动互联网的兴起,Web API不仅其他系统可以使用,手机端也可以使用,但是手机端也有相对特殊的地方,网络通信除了wifi, ...
- Win10 UWP 开发学习代码(不断更新)
页面之间跳转(传值) string txt = "Spring Lee"; this.Frame.Navigate(typeof(BlankPage1),txt); 另一个页面接收 ...
- 【技术贴】大型发布会现场的WiFi网络应该如何搭建?
WiFi网络的部署要远远比一般人想象的复杂,不是说放上几十个AP带宽就自动增加几十倍,恰恰相反,简单放几十个AP带宽会由于AP之间的竞争而 迅速使带宽下降为几乎不可用.实际上这个问题完全可以写一本书了 ...
- AutoHotKey实现将站点添加到IE的Intranet本地站点
最近在内部推行CRM系统,其中的CPQ组件要求必须将站点加入到"本地Intranet”才可以正常使用,但是由于使用用户比较多(超过几千人),并且每个用户的计算机水平都不一样,所以让用户手工去 ...
- 【Python】[面向对象编程] 访问限制,继承和多态
1.在Python中两个下划线__ 就是带便私有属性 private 注意已两个下划线开头并且结尾的 如 __init__ 是特殊变量,不是私有变量 2.多态,Python的“file-like ...
- 使用CocoaPods开发并打包静态库
Cocoapods作为OS X和iOS开发平台的类库管理工具,已经非常完善和强大.通常我们用pod来管理第三方开源类库,但我们也极有可能会开发一个用pod管理依赖关系的静态类库给其他人使用,而又不愿意 ...
- 软件开发学习笔记 <二>软件开发模型、Up、Rup、敏捷Up
软件开发过程(process) 是一个将用户需求转化为软件系统所需要的活动的集合. 软件生命周期(SDLC,Software Devlopment Life Cycle) 软件从孕育.诞生.成长.成熟 ...
- JavaScript中map函数和filter的简单举例(转)
js的数组迭代器函数map和filter,可以遍历数组时产生新的数组,和python的map函数很类似1)filter是满足条件的留下,是对原数组的过滤:2)map则是对原数组的加工,映射成一一映射的 ...