IOS设计模式-观察者模式
前言:23种软件设计模式中的观察者模式,也是在软件开发中,挺常用的一种设计模式。而在苹果开发中,苹果Cocoa框架已经给我们实现了这个设 计模式,那就是通知和KVO(Key-Value Observing),本篇博文将会先讲解通知和KVO的常用方法和使用示例,然后讲解观察者模式以及对观察者模式的实现。
文章内容大纲:
1、KVO的使用
2、通知的使用
3、观察者模式
正文:
1、KVO的使用
addObserver:forKeyPath:options:context:
通知其他对象的方法,这个方法在NSObject中就已经申明了,也就是说任何继承自NSObject的对象都可以使用KVO.
我们来实现一个对象a值改变的时候去通知对象b,也就是说这里b就是a的观察者,b观察a的变化,然后做出相应的反应.
Model_A.h和Model_A.m:
Model_B.h和Model_B.m:
最后在ViewController.h中:
输出结果:
2016-03-10 18:02:39.955 KVO[24772:539854] 程序开始执行!
2016-03-10 18:02:41.959 KVO[24772:539854] Model_B
-----------------------------------------------------------------------------------------------------------------------------------------------------------
如果注释掉Model_B中的方法observeValueForKeyPath:ofObject:change:context:,运行时会导致崩溃:
也就是这么一层关系:
A对象要通知B对象,B对象必须实现监听的方法,否则一旦有消息发送就会导致崩溃.
A对象不想通知B对象了,需要从B对象身上移除掉通知.
要想程序不出现问题,我们需要实现3步.
(主动添加B的通知) A -------> B(不实现一个方法就崩溃)
(主动移除B的通知) A ---X--> B
(重复移除B的通知) A ---X--> B(崩溃)
用起来很恶性,还好,我们可以重复添加B的通知而不崩溃......
但是要注意:添加的观察者的次数要和移除观察者的次数相等,少移除一个或者多移除一个都会造成程序崩溃:
2、 通知的使用
Model.h和Model.m
简易封装的通知中心类:Notification.h 和 Notification.m
在ViewController.m中:
输出结果:
2016-03-10 20:36:20.077 通知[28333:641372]
Hello,NSConcreteNotification 0x7fbafbd0b620 {name = A; userInfo = Hello,a}!
2016-03-10 20:36:20.078 通知[28333:641372]
Hello,NSConcreteNotification 0x7fbafbd0bca0 {name = B; userInfo = Hello,b}!
3、观察者模式
关于观察者模式,我们百度百科一下,会找到:
观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。
在这个图示例中,"订阅书刊的用户"需要向"书刊发行机构"提供基本的注册信息,这些信息包括用户自己的基本信息和要"订阅的书刊号",然后确定成为"
书刊发行机构"的用户,然后当"书刊发行机构"开始发行书刊,就会根据"订阅书刊的用户"的已经提供过的基本信息,进行发行书刊。然后"订阅书刊的用户"
就会得到相应的书刊。
在这个"发行-订阅"的模式中,"书刊发行机构"和"订阅书刊的用户"之间是靠"订阅书刊的用户"提供的基本有效的信息建立联系的。
这个"发行-订阅"的模式也是一种观察者模式的一个生活中非常生动的例子。"书刊发行机构"相当于观察者模式中的一个"通知中心"的角色,会根据实际需求根据用户信息向用户发送消息,然后用户作为观察者收到这些消息之后,就会自动的根据消息来执行自己的业务逻辑。
接下来,我们要实现通知中心的抽象设计
根据需求分析,首先我们需要一个唯一的"书刊发行机构",然后可以增加和删除书刊,同时能存储多个书刊,然后每个书刊又可以对应多个"订阅书刊的用户",
另外要补充一个就是,在添加和移除用户的接口中,我们需要传入用户信息对象,这个用户信息对象我们需要用协议来约束它,我们思考一下,比如订阅书刊,我
们当然需要用户最基本的两个信息,用户的ID和用户订阅的书刊号,用户的ID用于"书刊发行机构"能够准确的发消息或者发书刊正确无误的发对了人,这个作
用就好比我们唯一的身份证号码的作用是一样的。然后用户订阅的书刊号,就能保证"书刊发行机构"能把正确的书刊发到用户手中,不能随便什么书刊都发向随便
什么人的吧。
所以先写出下面所有的公开的接口,后面再具体实现它们,这就是面向接口设计:
另外,当"书刊发行机构"有了新的书刊的时候,根据需求,创建一个书刊号,然后如果有新的用户需要订阅新的书刊,根据需求,创建一个用户订阅书刊的信息对象。
一个书刊对应每个月会在某一天发布新书,当"书刊发行机构"的现有的书刊有了新的书发布的时候,就会发消息通知订阅这个书刊的用户,然后用户会做出及时的响应回馈。
按照观察者模式,被观察者发送消息,观察者收到消息就需要立马做出响应。这个和我们之前用的Cocoa框架已经实现的KVO和通知的模式是一样的。
为了实现这样的模式,我们还需要给用户信息对象用一个协议来约束它:
接着我们为上面的公开的接口具体实现,但是我们需要选择一个数据结构来存储书刊号和订阅书刊的用户信息对象,这里我选择使用NSMutableDictionary的Key-Value来存储书刊号和书刊,用NSHashTable来存储用户信息对象。
那么为什么要用NSHashTable来存储用户信息呢?为什么不用别的数据结构,比如数组(NSMutableArray)或者字典(NSMutableDictionary).
因为NSHashTable会对添加进的对象持有弱引用,当添加进来的元素,外部对他持有的强引用都取消的时候,这个对象就会自动从内存中消除,这样就不需要手动移除这些对象。
这个相比Cocoa给我们实现的KVO和通知,就不需要我们手动去操作实现removeObserve方法了。
虽然说,在使用NSHashTable实现的观察者模式,观察者对象本身就至少需要一个强引用,但是在实际开发中,观察者往往都至少会有一个强引用的。
所以,使用NSHashTable对系统算是一个小小的优化。
然后接着我们使用前面创造的观察者模式:
CustomerA.h和CustomerA.m:
在ViewController中,同时也把ViewController作为用户对象,以self传入:
打印:
2016-03-11 14:50:38.980 ObserverPattern[7958:175895] hashTable:NSHashTable {
[5] <ViewController: 0x7f93d2d26ac0>
[12] <CustomerA: 0x7f93d2c17f40>
}
2016-03-11 14:50:38.981 ObserverPattern[7958:175895] V1.0 SCIENCE
2016-03-11 14:50:38.981 ObserverPattern[7958:175895]
Hello,My Name is : CustomerA
V1.0--SCIENCE
备份的源码链接: http://pan.baidu.com/s/1eQTnm50 密码: s7su
4、自己实现KVO(以后有时间补上)
转载注明出处:http://www.cnblogs.com/goodboy-heyang/p/5265675.html ,尊重劳动成果。
本人最大的学习来源是阅读一直走在行业里很前面的大牛写的博客,有的博客还可能是一个团队写的,本人本篇深入学习的知识都是来自阅读它们的文章,中国有传统美德叫饮水思源,所以在这里也分享分享与本篇知识相关的学习资料来源(附有超链接,点击就能跳转):
1、《KVO的使用》
2、《通知中心NSNotificationCenter的使用》
3、《3种方式实现KVO并进行对比》
4、《手动设定实例变量的KVO实现监听》
5、《如何自己手动写一个KVO》
6、《需要罗列出所有的KVO的使用方法》
IOS设计模式-观察者模式的更多相关文章
- iOS设计模式和机制之观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 观察者模式的思想:当某对象改变时,观察者会 ...
- iOS设计模式(01):观察者
iOS设计模式(01):观察者 iOS-Observer-Pattern 什么是观察者模式 什么是观察者模式?你曾经订阅过报纸吗?在订阅报纸的时候,你不用去任何地方,只需要将你的个人地址信息以及订阅信 ...
- IOS设计模式浅析之单例模式(Singleton)
说在前面 进入正式的设计模式交流之前,扯点闲话.我们在项目开发的过程中,经常会不经意的使用一些常见的设计模式,如单例模式.工厂方法模式.观察者模式等,以前做.NET开发的时候,认真拜读了一下程杰老师的 ...
- iOS书摘之Objective-C编程之道 iOS设计模式解析
来自<Objective-C编程之道iOS设计模式解析>一书的摘要总结 一.Prototype 原型模式 定义:使用原型实例指定创建对象的种类,并通过复制这个原型创建新的对象.(<设 ...
- iOS 设计模式
很赞的总结 iOS Design Patterns 中文版 IOS设计模式之一(MVC模式,单例模式) IOS设计模式之二(门面模式,装饰器模式) IOS设计模式之三(适配器模式,观察者模式) IOS ...
- iOS设计模式 - (1)概述
近期可自由安排的时间比較多, iOS应用方面, 没什么好点子, 就先放下, 不写了.花点时间学学设计模式. 之后将会写一系列博文, 记录设计模式学习过程. 当然, 由于我自己是搞iOS的, 所以之后设 ...
- 18. 星际争霸之php设计模式--观察者模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- IOS设计模式之一(MVC模式,单例模式)
iOS 设计模式-你可能已经听说过这个词,但是你真正理解它意味着什么吗?虽然大多数的开发者可能都会认为设计模式是非常重要的,然而关于设计模式这一主题的文章却不多,并且有时候我们开发者在写代码的时候也不 ...
- iOS 设计模式之工厂模式
iOS 设计模式之工厂模式 分类: 设计模式2014-02-10 18:05 11020人阅读 评论(2) 收藏 举报 ios设计模式 工厂模式我的理解是:他就是为了创建对象的 创建对象的时候,我们一 ...
随机推荐
- 使用Python对Excel表格进行简单的读写操作(xlrd/xlwt)
算是一个小技巧吧,只是进行一些简单的读写操作.让人不爽的是xlrd和xlwt是相对独立的,两个模块的对象不能通用,读写无法连贯操作,只能单独读.单独写,尚不知道如何解决. #①xlrd(读) #cod ...
- C#+ html 实现类似QQ聊天界面的气泡效果
/**定义两个人的头像*/ Myhead = "<img src=qrc:/chatdemo/Msg/Head.png width='30px'heigth='30px'>&qu ...
- html5和css3的常用参考网
当我们使用HTML5, CSS3,甚至Bootstrap设计网站的时候,有些方面是必须考虑的,比如字体大小,标题大小,行间距,每行字数,字体,颜色,背景图片和文字的搭 配,图标,留白和布局...... ...
- Entity Framework 实体框架的形成之旅--基类接口的统一和异步操作的实现(3)
在本系列的第一篇随笔<Entity Framework 实体框架的形成之旅--基于泛型的仓储模式的实体框架(1)>中介绍了Entity Framework 实体框架的一些基础知识,以及构建 ...
- 从C#到Objective-C,循序渐进学习苹果开发(2)--Objective-C和C#的差异
本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台开发苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验. 在上篇<从C#到 ...
- 九个Console命令,让js调试更简单
一.显示信息的命令 最常用的就是console.log了. 二.占位符 console上述的集中度支持printf的占位符格式,支持的占位符有:字符(%s).整数(%d或%i).浮点数(%f)和对象( ...
- MVP的PV模式与SC模式
MVC是现今挺被推崇的一种架构模式,而MVP在MVC的基础对视图与模型上再解耦,使结构和各自的功能也有所改变.在去年鄙人也尝试了一下使用MVP做了一个小Demo,作为了MVC的一个变体,MVP还分了两 ...
- jquery属性选择器(同时匹配多个条件)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- serialize()序列化
- 孙鑫MFC学习笔记4:MFC画图
1.画线方法 *1.捕获鼠标按下和弹起消息,获取两个点 *2.消息响应,画线 2.在CMainFrame类中的鼠标左键事件得不到响应的原因是CNameView覆盖了CMainFrame 3.注释宏 4 ...