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

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

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

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

无论是作用域链,原型链,还是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. The P4 Language Specification v1.0.2 Header and Fields

    前言 本文参考P4.org网站给出的<The P4 Language Specification v1.0.2>的第二部分首部及字段,仅供学习:). 欢迎交流! Header and Fi ...

  2. caca393刷PTP教程

        http://www.chickenclix.com/ 让大家等急了,最近真是很忙,对不住了:)好了闲话少说开始讲正题,再说可能有人要拍砖了............我们就以http://www ...

  3. sqrt函数实现

    感谢杨工,让我更加认识到自己技术薄弱,这道题源自于和杨工的非正式面试,当时根本没思路,甚至没和查找有丝毫的联系,看来做自己想做的还是要付出努力的.sqrt()即开平方运算,y=x*x,已知Y的情况下求 ...

  4. 从 github 执行 git clone 一个大的项目时提示 error: RPC failed

    目前克隆一个比较大的项目,出现RPC failed的错误 Cloning into 'bigfiles'... remote: Counting objects: 190, done. remote: ...

  5. MZhong's Resume

    MATTHEW.ZHONG Male,27 Age Front-End Developer matthew.zhong@morningstar.com OBJECTIVE My objective i ...

  6. LVS的DR模式配置

    一.基本规划负载均衡调度器    192.168.1.104    默认网关    192.168.1.1    ip别名    192.168.1.233realserver1    192.168 ...

  7. 浅析C++的内存管理

    在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/ 静态存储区和常量存储区. 栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区.里面的变量通常是局部变量.函数参 ...

  8. Ngrok 内网穿透利器

    Ngrok是什么 Ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道.Ngrok 可捕获和分析所有通道上的流量,便于后期分析和重放 为什么要使用Ngrok ...

  9. 注册、启动、停止windows服务

    找到本机InstallUtil.exe命令 命令行下注册服务InstallUtil.exe D:\XXXXService.exe 启动服务 net start XXXXService 停止服务net ...

  10. 递归函数与fibonacci

    1.递归函数 1.1来个例子 def f(n): if n == 1: return 1 return n * f(n-1) print(f(5)) 结果为:120 即5的阶乘 通过这个例子来看递归函 ...