javascript职责链模式的代码怎么写
这篇“javascript职责链模式的代码怎么写”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“javascript职责链模式的代码怎么写”文章吧。
职责链的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象能处理它为止,传递链中的这些对象就叫节点。
需求背景:一个电商网站,用户交500定金且定金已付时,可享受500优惠券且不受货物数量限制;用户交200定金且定金已付时,可享受500优惠券且不受货物数量限制;用户不交定金时受货物数量限制,有货时原价买,无货时则无法买。
原始版本,ifelse
一路判断
varbuyOrder=function(orederType,pay,stock){if(orederType==1){if(pay){console.log('500优惠券');}else{if(stock>0){console.log('普通购物页面');}else{console.log('已无货');}}}elseif(orederType==2){if(pay){console.log('200优惠券');}else{if(stock>0){console.log('普通购物页面');}else{console.log('已无货');}}}elseif(orederType==3){if(stock>0){console.log('普通购物页面');}else{console.log('已无货');}}}buyOrder(1,true,600)
改进版本
varorder500=function(orderType,pay,stock){if(orderType=='1'&&pay==true){console.log('500优惠券');}else{order200(orderType,pay,stock)}}varorder200=function(orderType,pay,stock){if(orderType=='2'&&pay==true){console.log('200优惠券');}else{orderNormal(orderType,pay,stock)}}varorderNormal=function(orderType,pay,stock){if(stock>0){console.log('普通购物页面');}else{console.log('已无货');}}order500(3,true,0)
优化版本1:
同步的职责链
//3个订单函数,它们都是节点函数varorder500=function(orderType,pay,stock){if(orderType=='1'&&pay==true){console.log('500优惠券');}else{return'nextSuccessor';//我不知道下个节点是谁,反正把请求往后传递}}varorder200=function(orderType,pay,stock){if(orderType=='2'&&pay==true){console.log('200优惠券');}else{return'nextSuccessor';//我不知道下个节点是谁,反正把请求往后传递}}varorderNormal=function(orderType,pay,stock){if(stock>0){console.log('普通购物页面');}else{console.log('已无货');}}//职责构造函数varChain=function(fn){this.fn=fn;this.successor=null;}Chain.prototype.setNextSuccessor=function(successor){//设置职责顺序方法this.successor=successor}Chain.prototype.passRequest=function(){//请求传递varret=this.fn.apply(this,arguments)if(ret==='nextSuccessor'){returnthis.successor&&this.successor.passRequest.apply(this.successor,arguments)}returnret;}//把3个订单函数分别包装成职责链的节点varchainOrder500=newChain(order500)varchainOrder200=newChain(order200)varchainOrderNormal=newChain(orderNormal)//然后指定节点在职责链中的顺序chainOrder500.setNextSuccessor(chainOrder200)chainOrder200.setNextSuccessor(chainOrderNormal)//最后把请求传递给第一个节点,开启职责链模式传递chainOrder500.passRequest(1,true,500)//500优惠券chainOrder500.passRequest(3,true,20)//普通购物页面chainOrder500.passRequest(3,true,0)//已无货//此时如果中间有需求改动,只需如此做:varorder300=function(){if(orderType=='3'&&pay==true){console.log('300优惠券');}else{return'nextSuccessor';//我不知道下个节点是谁,反正把请求往后传递}}varchainOrder300=newChain(order300)//添加新职责节点chainOrder500.setNextSuccessor(chainOrder300)chainOrder300.setNextSuccessor(chainOrder300)//修改职责链顺序chainOrder200.setNextSuccessor(chainOrderNormal)//这样,就可以完全不必去理会原来的订单函数代码,只需增加一个节点,然后重新设置职责链中的相关节点的顺序就行。
优化版本2:异步的职责链
在实际开发中,经常会遇到 一些异步的问题,比如要在节点函数中发起一个ajax请求,异步请求返回的结果才能决定是否继续在职责链中passRequest
可以给Chain类再增加一个原型方法:
//职责构造函数varChain=function(fn){this.fn=fn;this.successor=null;}Chain.prototype.setNextSuccessor=function(successor){//设置职责顺序方法this.successor=successor}Chain.prototype.passRequest=function(){//请求传递varret=this.fn.apply(this,arguments)if(ret==='nextSuccessor'){//传递给职责链中的下一个节点returnthis.successor&&this.successor.passRequest.apply(this.successor,arguments)}returnret;}//新增,表示手动传递请求给职责链中的下一个节点Chain.prototype.next=function(){returnthis.successor&&this.successor.passRequest.apply(this.successor,arguments)}//异步职责链例子varfn1=newChain(function(){console.log(1);return'nextSuccessor'})varfn2=newChain(function(){console.log(2);varself=this;setTimeout(function(){self.next()},1000)})varfn3=newChain(function(){console.log(3);})//指定节点在职责链中的顺序fn1.setNextSuccessor(fn2)fn2.setNextSuccessor(fn3)//把请求传递给第一个节点,开始节点传递fn1.passRequest()//输出12...(1秒后)...3//这是一个异步职责链,请求在职责链节点中传递,但节点有权利决定什么时候把请求交给下一个节点。这样可以创建一个异步ajax队列库。
tips:
这里补充个知识点:“短路求值”&&
会返回第一个假值(0, null, "", undefined, NaN)
,而||
则会返回第一个真值。
var x = a || b || c
等价于:
varx;if(a){x=a;}elseif(b){x=b;}else{x=c;}
var x = a && b && c
等价于:
varx=a;if(a){x=b;if(b){x=c;}}
所以&&
有时候会用来代替if (expression) doSomething()
,转成&&
方式就是expression && doSomething()
。
而||
比较用来在函数中设置默认值,比如:
functiondoSomething(arg1,arg2,arg3){arg1=arg1||'arg1Value';arg2=arg2||'arg2Value';}
不过还需要看具体的使用场景,就比如如果要求doSomething()
传入的 arg1 为一个数值,则上面的写法就会出现问题(在传入 0 的时候被认为是一个假值而使用默认值)。
现在个人比较常用的方法只判断是否与undefined
相等,比如
functiondoSomething(arg){arg=arg!==void0?arg:0;}
职责链模式的优势:解耦请求发送者和 N 个接收者之间的复杂关系,由于不知道链条中的哪个节点可以处理你发出的请求,所以只需把请求传递给第一个节点就行。
如果在实际开发中,当维护一个含有多个条件分支语句的巨大函数时时,可以使用职责链模式。链中的节点对象可以灵活拆分重组,增加删除节点,且无需改动其他节点函数内的代码。
以上就是关于“javascript职责链模式的代码怎么写”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。