js设计模式之职责链模式
一. 初始职责链模式
定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者的关系,将这个对象连成一条链,并沿着一条链传递该请求,直到一个对象处理它为止。
可能有点晦涩难懂,我们来看一个例子,比如说你妈让你出去打酱油,此时我的请求就是买一瓶酱油回来,你会出门先去离你家最近的超市买酱油,如果没有,你会去下一个超市,知道有一个超市买到了酱油,也就结束了这条链的传递,超市就相当于处理请求的一条对象链,这就是职责链模式,我们想办法用代码实现它。
二. 代码实现
需求:我们来实现生活中的一个例子,商品的优惠活动,有三种情况,第一种是500元订金100元优惠券,第二种是200元订金50元优惠券,第三种是无优惠。
此时我们首先想到的做法肯定使用条件分支来判断属于哪一种优惠,虽然可以达到目的,但是代码的可维护性太低,我们可以使用职责链模式来实现。
1. 灵活可拆分的职责链节点
分析:首先我们将每一次优惠作为单独封装,判断请求是否满足此次优惠条件,如果不满足,则向下传递,直到满足优惠条件为止。
let order500 = function( orderType, pay, stock ) {if( orderType == 1 && pay == true) {console.log(" 500元订金,得到100元优惠券");}else{return 'nextSuccessor';}}let order200 = function( orderType, pay, stock ){if( orderType == 2 && pay == true ) {console.log(" 200元订金,得到50元优惠券");}else{return 'nextSuccessor';}}let orderNormal = function( orderType, pay, stock ) {if(stock > 0) {console.log("普通购买,无优惠券");}else{console.log("手机库存不足");}}// 包装节点let Chain = function( fn ){this.fn = fn;this.successor = null;}Chain.prototype.setNextSuccessor = function( successor ) {return this.successor = successor;}Chain.prototype.passRequest = function() {let ret = this.fn.apply(this, arguments);if( ret === "nextSuccessor") {return this.successor && this.successor.passRequest.apply(this.successor, arguments);}return ret;}// 创建职责链节点let chainOrder500 = new Chain( order500 );let chainOrder200 = new Chain( order200 );let chainOrderNormal = new Chain( orderNormal );chainOrder500.setNextSuccessor( chainOrder200 ).setNextSuccessor(chainOrderNormal);chainOrder500.passRequest(1, true, 500);chainOrder500.passRequest(2, true, 500);2. 异步的职责链
分析:有时我们的请求可能不是那么顺畅,比如获取请求时,请求数据拿回来可能有延迟,我们根据拿到的数据来判断是否进行再次的请求,因此我们需要设置主动向下一节点传递请求,通过异步实现。
// 包装节点let Chain = function( fn ){this.fn = fn;this.successor = null;}Chain.prototype.setNextSuccessor = function( successor ) {return this.successor = successor;}Chain.prototype.passRequest = function() {let ret = this.fn.apply(this, arguments);if( ret === "nextSuccessor") {return this.successor && this.successor.passRequest.apply(this.successor, arguments);}return ret;}Chain.prototype.next = function() {return this.successor && this.successor.passRequest.apply( this.successor, arguments);}// 创建职责链节点let fn1 = new Chain(()=>{console.log(1);return 'nextSuccessor';})let fn2 = new Chain(function(){console.log(2);let self = this;setTimeout(()=>{self.next();}, 2000);})let fn3 = new Chain(()=>{console.log(3);})fn1.setNextSuccessor( fn2 ).setNextSuccessor( fn3 );fn1.passRequest();3. 用 AOP 实现职责链
分析:用 AOP 来实现虽然简单巧妙,但是将函数叠在一起,也叠加了函数的作用域,如果两天太长会对性能有较大影响。
Function.prototype.after = function( fn ) {let self = this;return function() {let ret = self.apply(this, arguments);if(ret === 'nextSuccessor') {fn.apply( this, arguments );}return ret;}}let order = order500.after( order200 ).after( orderNormal );order(3, true, 500);三. 总结
优点:1. 解耦了请求的发送者和 N 个接收者之间的 复杂关系
2. 每个对象可有灵活拆分,控制请求的入口和长度
缺点: 1. 可能某次传递中大部分节点都只是作为传递,并没有多大的用处,造成性能损耗
无论是作用域链,原型链,还是冒泡事件中都合适的应用了职责链模式。职责链模式还可以和组合模式结合在一起,用来连接部件和父部件,或者提高组合对象的效率。
总结
以上是生活随笔为你收集整理的js设计模式之职责链模式的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: linux的FHS目录结构简要介绍
- 下一篇: 常用设计模式——职责链模式