一、职责链的定义和使用场景

职责链模式的定义是,职责链模式将一系列可能会处理请求的对象连接成一条链,请求在这些对象之间一次传递,直到遇到一个可以处理它的对象。从而避免请求的发送者和接收者之间的耦合关系。

职责链模式的优点是:请求发送者只需要直到链中的第一个节点,从而解耦了发送者和一组接收者之间的强联系。此外,使用了职责链模式之后,链中的节点对象可以灵活地拆分重组,增加或者删除 一个节点,以及改变节点在链中的位置都是轻而易举的。

职责链模式的缺点是:首先不能保证某个请求一定会被链中的某个节点处理,这种情况系下可以在链尾增加一个保底的接受者节点来处理这种即将离开链尾的请求。其次,职责链模式使得程序中多了一些节点对象,可能在某一次的请求传递过程中,大部分的节点并没有起到实质性的作用,从性能的角度考虑,应当避免过长的职责链带来的性能损耗。

无论是作用域链,原型链,还是DOM节点中的事件冒泡,从中都可以找到职责链模式的影子。

结合自己开发经验,在轻量级MVVM的实现中,就体现了职责链的设计模式。

1.具有指向下一个节点的属性:this.parent

2.在具体的事件处理函数中进行递归调用,以便事件沿着职责链的方向传递(冒泡?)

二、职责链模式应用案例

假设有这么一种场景:一个售卖手机的电商网站,经过分别交纳500元定金和200元定金的两轮预订之后(订单在此时已经生成),现在进入了正式购买阶段。

公司针对支付过定金的客户有一定的优惠,正式购买之后,已经支付过500元定金的用户会收到100元优惠券,200元定金的用户可以收到50元优惠券,没有支付过定金的只能进入普通购买方式,也就是没有优惠券。相关的字段有这么几种:

oederType:订单类型,为1代表500元定金用户,2代表200元定金用户,3为普通购买用户;

    //职责链模式学习
var order500=function(orderType,pay,stock){
if(orderType==&&pay===true){
console.log('500元定金预约,得到100元优惠券');
}else{
return 'nextSuccessor';
}
};
var order200=function(orderType,pay,stock){
if(orderType===&&pay===true){
console.log('200元定金预约,得到50优惠券');
}else{
return 'nextSuccessor';
}
}; var orderNormal=function(orderType,pay,stock){
if(stock>){
console.log('普通购买,无优惠券');
}else{
return 'nextSuccessor';
}
};

接下来需要把函数包装进职责链节点:

//职责链包装

    var Chain=function(fn){
this.fn=fn;
this.nextSuccessor=null;
}; Chain.prototype.setNextSuccessor=function(successor){
return this.nextSuccessor=successor;
}; Chain.prototype.passRequest=function(){
var ret=this.fn.apply(this,arguments); if(ret=='nextSuccessor'){
//console.log(this.nextSuccessor.fn.name);
return this.nextSuccessor&&this.nextSuccessor.passRequest.apply(this.nextSuccessor,arguments);//启动这一步启动递归了
}
return ret;
}; //测试
var chainOrder500=new Chain(order500);
var chainOrder200=new Chain(order200);
var chainOrderNormal=new Chain(orderNormal); chainOrder500.setNextSuccessor(chainOrder200);
chainOrder200.setNextSuccessor(chainOrderNormal); //将请求传递给第一个节点即可
chainOrder500.passRequest(,true,);//输出 500元定金,得到100元优惠券
chainOrder500.passRequest(,true,);//输出200元定金,得到50元优惠券
chainOrder500.passRequest(,false,); //输出 手机库存不足

三、异步的职责链

在之前的职责链中,我们让每个节点都返回一个特定值nextSuccessor,来表示将请求传递给下一个节点,在现实生活中,经常会遇到一些异步的问题,比如发送ajax请求,由ajax请求的结果来决定是否传递给下一个节点,此时同步返回nextSuccessor已经没有意义了,需要给Chain类增加Chain.prototype.next,用于手动传递请求给下一个节点。

    Chain.prototype.next=function(){
return this.nextSuccessor&&this.nextSuccessor.passRequest.apply(this.nextSuccessor,arguments);
};

四、使用AOP的方式实现职责链

之前的案例采用Chain将普通函数包装成职责链的节点,实际上有一种更加方便的方式来创建职责链。

    //使用AOP的方式创建职责链
Function.prototype.after=function(afterFn){
var self=this;
return function(){
var ret=self.apply(this,arguments);
if(ret==='nextSuccessor'){
ret=afterFn.apply(this.arguments);
}
return ret;
}; }; var order=order500.after(order200).after(orderNormal);
order(,false,);

javascript设计模式学习之十三——职责链模式的更多相关文章

  1. atitit.设计模式(1)--—职责链模式(chain of responsibility)最佳实践O7 日期转换

    atitit.设计模式(1)---职责链模式(chain of responsibility)最佳实践O7 日期转换 1. 需求:::日期转换 1 2. 可以选择的模式: 表格模式,责任链模式 1 3 ...

  2. 重温设计模式(三)——职责链模式(chain of responsibility)

    一. 写在前面的 这么多的设计模式,我觉得职责链是我第一次看上去最简单,可是回想起来却又最复杂的一个模式. 因此,这个文章我酝酿了很久,一直也没有胆量发出来,例子也是改了又改,可是仍然觉得不够合理.所 ...

  3. C#设计模式之二十一职责链模式(Chain of Responsibility Pattern)【行为型】

    一.引言   今天我们开始讲"行为型"设计模式的第八个模式,该模式是[职责链模式],英文名称是:Chain of Responsibility Pattern.让我们看看现实生活中 ...

  4. C#设计模式之二十职责链模式(Chain of Responsibility Pattern)【行为型】

    一.引言 今天我们开始讲“行为型”设计模式的第八个模式,该模式是[职责链模式],英文名称是:Chain of Responsibility Pattern.让我们看看现实生活中的例子吧,理解起来可能更 ...

  5. js设计模式(12)---职责链模式

    0.前言 老实讲,看设计模式真得很痛苦,一则阅读过的代码太少:二则从来或者从没意识到使用过这些东西.所以我采用了看书(<js设计模式>)和阅读博客(大叔.alloyteam.聂微东)相结合 ...

  6. 设计模式 --> (15)职责链模式

    职责链模式 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 示例 考虑员工要求加薪.公司的管理者一共有 ...

  7. JS设计模式(10)职责链模式(重要)

    什么是职责链模式? 重要性:4 星,在项目中能对 if-else 语句进行优化 定义:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到 ...

  8. javascript设计模式学习之十六——状态模式

    一.状态模式的定义 状态模式的关键是区分事务内部和外部的状态,事务内部状态改变往往会带来事务的行为改变. 状态模式中有意思的一点是,一般我们谈到封装,都是优先封装对象的行为,而非对象的状态.但在状态模 ...

  9. JavaScript设计模式学习——builder pattern(建造者模式)

    个人理解的应用场景 举个例子,比如想要创建各种类型的车的实例,车的类型有很多种,但创建每种类型车的接口定义可能是一样的,就用到了此模式 相关概念的通俗解释 上述例子中接口的定义叫builder 接口到 ...

随机推荐

  1. JavaScript系列:函数 自执行 表达式 声明 定义

    可用方式 (function($) {})(jQuery); !function( $ ){}(jQuery); +function( $ ){}(jQuery); -function( $ ){}( ...

  2. 将url的查询参数解析成字典对象

    1, 这个题目不约而同的出现在了多家公司的面试题中,当然也是因为太过于典型,解决方案无非就是拆字符或者用正则匹配来解决,我个人强烈建议用正则匹配,因为url允许用户随意输入,如果用拆字符的方式,有任何 ...

  3. thrift

    环境准备: 1.下载window版本的thrift编译器 2.下载idea的thirft插件 3.设置thrift编译工具为:步骤1下载的编译器 4.编写thrift文件 namespace java ...

  4. CSS权威指南 - 浮动和定位 2

    定位 定位的想法很简单元素框相对于正常位置出现在哪里. 定位:static,相对, 绝对, fixed, 继承 static就是默认的位置 相对就是相对于默认位置的偏移.原来的static定位位置依然 ...

  5. PHP 设计模式 笔记与总结(9)数据对象映射模式

    [数据对象映射模式] 是将对象和数据存储映射起来,对一个对象的操作会映射为对数据存储的操作.例如在代码中 new 一个对象,使用数据对象映射模式就可以将对象的一些操作比如设置一些属性,就会自动保存到数 ...

  6. C++ 常用术语(后续补充)

    内存对齐常量折叠 堆栈解退(stack unwinding) 模板特化模板偏特化 模板实例化 函数对象 单一定义规则(One-Definition Rule,ODR) 自引用   对象切片(objec ...

  7. ExtJS笔记4 容器与布局(Layouts and Containers)

    The layout system is one of the most powerful parts of Ext JS. It handles the sizing and positioning ...

  8. Nginx 配置文件模板

    user www www; worker_processes 2; error_log /usr/local/nginx/logs/nginx_error.log crit; pid /usr/loc ...

  9. Syntactic_sugar

    https://en.wikipedia.org/wiki/Syntactic_sugar http://stackoverflow.com/questions/11366006/mysql-on-v ...

  10. mysql 密码篇

    通过MySQL命令行,可以修改MySQL数据库的密码,下面就为您详细介绍该MySQL命令行,如果您感兴趣的话,不妨一看. 格式:mysqladmin -u用户名 -p旧密码 password 新密码 ...