深入理解JavaScript系列(38):设计模式之职责链模式
介绍 职责链模式(Chain of responsibility)是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。 也就是说,请求以后,从第一个对象开始,链中收到请求的对象要么亲自处理它,要么转发给链中的下一个候选者。提交请求的对象并不明确知道哪一个对象将会处理它——也就是该请求有一个隐式的接受者(implicit receiver)。根据运行时刻,任一候选者都可以响应相应的请求,候选者的数目是任意的,你可以在运行时刻决定哪些候选者参与到链中。 正文 对于JavaScript实现,我们可以利用其原型特性来实现职责链模式。 var NO_TOPIC = -1;
var Topic; function Handler(s, t) {
this.successor = s || null;
this.topic = t || 0;
} Handler.prototype = {
handle: function () {
if (this.successor) {
this.successor.handle()
}
},
has: function () {
return this.topic != NO_TOPIC;
}
}; Handler只是接受2个参数,第一个是继任者(用于将处理请求传下去),第二个是传递层级(可以用于控制在某个层级下是否执行某个操作,也可以不用),Handler原型暴露了一个handle方法,这是实现该模式的重点,先来看看如何使用上述代码。 var app = new Handler({
handle: function () {
console.log('app handle');
}
}, 3); var dialog = new Handler(app, 1); var button = new Handler(dialog, 2); button.handle(); 改代码通过原型特性,调用代码从button.handle()->dialog.handle()->app.handle()->参数里的handle(),前三个都是调用原型的handle,最后才查找到传入的参数里的handle,然后输出结果,也就是说其实只有最后一层才处理。 那如何做到调用的时候,只让dialog的这个对象进行处理呢?其实可以定义dialog实例对象的handle方法就可以了,但需要在new button的之前来做,代码如下: var app = new Handler({
handle: function () {
console.log('app handle');
}
}, 3); var dialog = new Handler(app, 1);
dialog.handle = function () {
console.log('dialog before ...')
// 这里做具体的处理操作
console.log('dialog after ...')
}; var button = new Handler(dialog, 2); button.handle(); 该代码的执行结果即时dialog.handle里的处理结果,而不再是给app传入的参数里定义的handle的执行操作。 那能不能做到自身处理完以后,然后在让继任者继续处理呢?答案是肯定的,但是在调用的handle以后,需要利用原型的特性调用如下代码: Handler.prototype.handle.call(this); 该句话的意思说,调用原型的handle方法,来继续调用其继任者(也就是successor )的handle方法,以下代码表现为:button/dialog/app三个对象定义的handle都会执行。 var app = new Handler({
handle: function () {
console.log('app handle');
}
}, 3); var dialog = new Handler(app, 1);
dialog.handle = function () {
console.log('dialog before ...')
// 这里做具体的处理操作
Handler.prototype.handle.call(this); //继续往上走
console.log('dialog after ...')
}; var button = new Handler(dialog, 2);
button.handle = function () {
console.log('button before ...')
// 这里做具体的处理操作
Handler.prototype.handle.call(this);
console.log('button after ...')
}; button.handle(); 通过代码的运行结果我们可以看出,如果想先自身处理,然后再调用继任者处理的话,就在末尾执行Handler.prototype.handle.call(this);代码,如果想先处理继任者的代码,就在开头执行Handler.prototype.handle.call(this);代码。 总结 职责链模式经常和组合模式一起使用,这样一个构件的父构件可以作为其继任者。 同时,DOM里的事件冒泡机制也和此好像有点类似,比如点击一个按钮以后,如果不阻止冒泡,其click事件将一直向父元素冒泡,利用这个机制也可以处理很多相关的问题,比如本系列设计模式享元模式里的《例1:事件集中管理》的示例代码。 参考代码:https://gist.github.com/1174982 同步与推荐 本文已同步至目录索引:深入理解JavaScript系列 深入理解JavaScript系列文章,包括了原创,翻译,转载等各类型的文章,如果对你有用,请推荐支持一把,给大叔写作的动力。
深入理解JavaScript系列(38):设计模式之职责链模式的更多相关文章
- php设计模式之职责链模式
<?php /** * @desc php设计模式之职责链模式(责任链模式) 定义:顾名思义,责任链模式为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这 ...
- 设计模式之职责链模式(JAVA实现)
学习netty框架时,看到有人说netty用到了设计模式的职责链模式,学习一下职责链模式,主要参考大话设计模式. 主要场景: 小菜想要加薪,向经理提出加薪请求,经理没有权限,经理交由总监处理,总监也没 ...
- 设计模式-利用职责链模式消除if
本文是对职责链设计模式的应用(变种),所以假设读者已经掌握了职责链设计模式,职责链模式只会应景简介. 本文主要内容: 需求(ShitCode) 职责链模式简介 设计理念 代码演示(消除if) 应用总结 ...
- 深入理解JavaScript系列(50):Function模式(下篇)
介绍 本篇我们介绍的一些模式称为初始化模式和性能模式,主要是用在初始化以及提高性能方面,一些模式之前已经提到过,这里只是做一下总结. 立即执行的函数 在本系列第4篇的<立即调用的函数表达式> ...
- 深入理解JavaScript系列(49):Function模式(上篇)
介绍 本篇主要是介绍Function方面使用的一些技巧(上篇),利用Function特性可以编写出很多非常有意思的代码,本篇主要包括:回调模式.配置对象.返回函数.分布程序.柯里化(Currying) ...
- JavaScript设计模式_10_职责链模式
职责链模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止.职责链模式的名字非常形象,一系列可能 ...
- 设计模式:职责链模式(Chain Of Responsibility)
定 义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止. 结构图: 处理请求类: //抽象处理类 abs ...
- 设计模式之职责链模式(Chain of Responsibility)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- php实现设计模式之 职责链模式
<?php /** * 职责链模式 * * 为解除请求的发送者和接收者之间的耦合,而使用多个对象都用机会处理这个请求,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它 * 抽象 ...
随机推荐
- 徒手CPR心脏复苏
CPR 缩写于cardiopulmonary resuscitation. 在危难时刻,能救人救命,意义极其重大,赶紧学起来 成人的CPR 第一步:检查意识 靠近其耳朵,在两耳旁交替大声喊:「你怎么了 ...
- 如何安全地运行用户的 JavaScript 脚本
本文来自网易云社区,转载务必请注明出处. 有时候我们需要运行用户输入的 JavaScript 脚本(以下简称脚本).对于我们来说,这些脚本是不可信任的,如果在当前的 Context 中运行这些脚本,它 ...
- windows server2008 r2安装DNS服务器
1.开始->管理工具->服务器管理器 2.角色->添加角色 3.服务器角色->DNS服务器 4.一直点击下一步,直至安装完成. (确认步骤时会提示,可能会需要重启服务器) 安装 ...
- jquery源码解析:jQuery静态属性对象support详解
jQuery.support是用功能检测的方法来检测浏览器是否支持某些功能.针对jQuery内部使用. 我们先来看一些源码: jQuery.support = (function( support ) ...
- ios 字符串处理:截取字符串、匹配字符串、分隔字符串
1.截取字符串 NSString*string =@"sdfsfsfsAdfsdf";string = [string substringToIndex:7];//截取掉下标7之后 ...
- loj #6032. 「雅礼集训 2017 Day2」水箱 线段树优化DP转移
$ \color{#0066ff}{ 题目描述 }$ 给出一个长度为 \(n\) 宽度为 \(1\) ,高度无限的水箱,有 \(n-1\) 个挡板将其分为 \(n\) 个 \(1 - 1\) 的小格, ...
- 对cookie,session,token,jwt的理解
对这几个东西有点凌乱了,今天有时间整理下 cookie Cookie的诞生 由于HTTP协议是无状态的,而服务器端的业务必须是要有状态的.Cookie诞生的最初目的是为了存储web中的状态信息,以方便 ...
- Maven 远程仓库下载慢的的解决方案
配置很简单,修改conf文件夹下的settings.xml文件,添加如下镜像配置: 我直接去设置maven目录下面的setttings文件 添加镜像站点 <mirrors> <mir ...
- weex 初始化
文档教程 一. 已有项目集成weex, 有时候会报错, 因为sdk中用到了socket pod 'WeexSDK' pod 'SocketRocket' 二. 在app启动方法 -didFinish ...
- String字符串补位
String类的format()方法用于创建格式化的字符串以及连接多个字符串对象.熟悉C语言的读者应该记得C语言的sprintf()方法,两者有类似之处.format()方法有两种重载形式. l ...