2022年2022年观察者模式 .pdf
《2022年2022年观察者模式 .pdf》由会员分享,可在线阅读,更多相关《2022年2022年观察者模式 .pdf(10页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、观察者模式第 15 章事件驱动的环境中, 比如浏览器这种持续寻求用户关注的环境中,观察者模式又名 发布者 订阅者 (publisher-subscriber )模式是一种管理人与其任务之间的关系(确切地讲,是对象及其行为和状态之间的关系)的得力工具。 用JavaScript 的话来说, 这种模式的实质就是你可以对程序中某个对象的状态进行观察,并且在其发生改变时能够得到通知。在观察者模式中存在两个角色:观察者和被观察者。本书一般倾向于称其为发布者 和订阅者 。这种模式在 JavaScript 中有几种不同的实现方式, 本章将对其中的一些实现方式进行考察。不过我们首先要说明一下发布者和订阅者这两种
2、角色。下一节的例子以报业为例说明了观察者模式的工作方式。15.1示例:报纸的投送在报纸行业中,发行和订阅的顺利进行有赖于一些关键性的角色和行为。首先是读者。他们都是订阅者 (subscriber ) ,是与你我一样的人。我们消费数据并且根据读到的消息做出反应。我们可以选择自己的居住地点,让报社把报纸送到自己家中。这个活动中的另一个角色是发行方(publisher) 。他们负责出版诸如 San Francisco Chronicle、New York Times 和Sacramento Bee 这样的报纸。确定了各方的身份之后,我们就可以分析每一方的职责所在。作为报纸的订阅者,我们有一些事要做。
3、数据到来的时候我们收到通知。我们消费数据。然后我们根据数据做出反应。只要报纸到了订阅者手中,他们就可以自行处置。有些人读完之后会将其扔在一边,有些人会向朋友或家人转述其中的新闻, 甚至还有一些人会把报纸送回去。 总而言之,订阅者要从发行方 接收数据。发行方则要 发送 数据。在本例中,发行方也是投送方(deliver) 。一般说来,一个发行方很可能有许多订阅者,同样,一个订阅者也很可能会订阅多家报社的报纸。问题的关键在于,这是一种多对多的关系,需要一种高级的抽象策略,以便订阅者能够彼此独立地发生改变,而发行方能够接受任何有消费意向的订阅者。21515.1.1推与拉的比较对于报社来说, 只为给几个
4、订阅者投送报纸就满世界跑是不划算的。而纽约市的居民也不可能特意飞到旧金山去拿自己订的San Francisco Chronicle, 要知道这份报纸可以直接投送到他们家名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 10 页 - - - - - - - - - 198第 15 章 观察者模式门口。订阅者要想拿到报纸的话有两种投送方式可选:推或拉。在推环境中,发行方很可能会雇佣投送人员四处送报。换句话说,他们把自己的报纸推出去,让订阅者收取。在拉环境中,规模较小的本地报社可
5、能会在订阅者家附近的街角提供自己的数据,供订阅者“拉”。那些成长型发行方没有足够的资源进行大规模投送,因此采用拉方案, 让订阅者到当地的杂货店或自动售货机那里“拿”报,对于它们来说往往是个优化投送环节的好办法。15.1.2模式的实践在JavaScript 中有多种方法可以实现发布者 订阅者模式。在展示那些示例之前,我们先确保各种角色的扮演者(对象)及其行为(方法)都已就绪。订阅者可以订阅和退订。他们还要接收。他们可以在“由人投送(being delivered to ) ”和“自己收取( receiving for themselves ) ”之间进行选择。发布者负责投送。他们可以在“送出(g
6、iving) ”和“由人取( being taken from) ”之间进行选择。下面是一个展示发布者和订阅者之间的互动过程的高层示例。它是Sells方法( Sellsian approach )的一个示范。这种技术类似于测试驱动的开发(TDD ) ,不过它要求先写实现代码,就像API已经写好了一样。为了让这些代码成为可运转的真正实现,程序员需要完成各种该做的工作, API由此形成:216 这不是一个正式的术语,而是Don Box 发明的一个词,用来指Chris Sells 所说的一种开发方法。下面的代码中开头部分的注释中那个URL 就是该词的出处。译者注名师资料总结 - - -精品资料欢迎下
7、载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 10 页 - - - - - - - - - 15.1示例:报纸的投送 199 在这个模型中,可以看出发布者处于明显的主导地位。它们负责登记其顾客,而且有权停止为其投送。最后,新的报纸出版后它们会将其投送给顾客。上面的代码创建了一个新的可观察 (observable )对象。它有三个实例方法:subscribe- Customer、unSubscribeCustomer和deliver。subscribeCustomer方法以一个代表订阅者的回调函数为参数。de
8、liver方法在调用过程中将通过这些回调函数把数据发送给每一个订阅者。下面的例子处理的是同一类问题,但发布者和订阅者之间的互动方式有所不同:217名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 10 页 - - - - - - - - - 200第 15 章 观察者模式在这个例子中, 发布者的创建方式和订阅者接收数据的方式没有多少改变,但拥有订阅和退订权的一方变成了订阅者。当然,负责发送数据的还是发布者一方。本例中的发布者是Publisher类的实例。它有一个delive
9、r方法。而作为订阅者的函数对象则拥有subscribe和unsubscribe两个方法。订阅者只是普通的回调函数,那两个方法是通过扩展Function的prototype而加入的。下面我们将一步一步地构建出符合需要的API。15.2构建观察者API 在明确了观察者模式中的核心成员之后,现在可以着手构建其API了。首先,我们需要一个发布者的构造函数,它为该类实例定义了一个类型为数组的属性,用来保存订阅者的引用:218 因为任何函数都是Function的实例,所以在Function.prototype中添加的新方法会被所有函数继承。当然,这里把subscribe和unsubscribe添加到 Fu
10、nction.prototype中只是为了省事,在实际项目中不应该这样做。译者注名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 10 页 - - - - - - - - - 15.2构建观察者API201 15.2.1投送方法所有Publisher实例都应该能够投送数据。只要把deliver方法添加到Publisher的prototype中,它就能够被所有Publisher对象共享:这个方法使用 JavaScript 1.6 中新增的数组方法forEach(参见“ Moz
11、illa 开发人员中心”网站http:/developer.mozilla.org/)逐一处理每一个订阅者。forEach方法会对一个“草垛( haystack ) ”从头到尾访问一遍,把每一根“针(needle ) ” 、 “针”的索引和整个数组提供给一个回调方法。订阅者数组中的每根“针”都是一个回调函数,比如Joe、Lindsay和Quadaras。deliver方法把this用作返回值,因此可以对该方法进行链式调用(参见第6章) ,以连续不断地投送数据。15.2.2订阅方法下一步是给予订阅者订阅的能力:这段代码为Function的prototype添加了一个以Publisher对象为参数
12、的subscribe方法,因此所有函数都能调用这个方法。subscribe方法先定义了一个that变量,并把this赋给219这里所谓的“草垛”和“针”分别指数组及其元素。这里所说的回调函数,是指forEach方法的那个参数。这个回调函数本身又有三个参数,依次为当前数组元素(即“针”) 、当前数组元素的索引值、数组。本例中的那个回调函数是一个匿名函数,它只使用了第一个参数。注意,本段最后那句话“订阅者数组中的每根针都是一个回调函数”中的“回调函数”与前面说的那个回调函数不是一回事。译者注名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - -
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022年2022年观察者模式 2022 观察者 模式
限制150内