- JavaScript 设计模式之用 AOP 实现职责链
- JavaScript 设计模式之职责链模式的优缺点
- JavaScript 设计模式之异步的职责链
- JavaScript 设计模式之用职责链模式重构代码
- JavaScript 设计模式之现实中的职责链模式
首先改写下分别表示3种购买模式的节点函数,如果某个节点不能处理请求,则返回一个特定的字符串“nextSuccessor
”来表示该请求需要继续往后面传递。
// 500 元订单 var order500 = function (orderType, pay, stock) { if (orderType === 1 && pay === true) { console.log('500 元定金预购, 得到 100 优惠券'); } else { return 'nextSuccessor'; // 我不知道下一个节点是谁,反正把请求往后面传递 } }; // 200 元订单 var order200 = function (orderType, pay, stock) { if (orderType === 2 && pay === true) { console.log('200 元定金预购, 得到 50 优惠券'); } else { return 'nextSuccessor'; // 我不知道下一个节点是谁,反正把请求往后面传递 }; } // 普通购买订单 var orderNormal = function (orderType, pay, stock) { if (stock > 0) { console.log('普通购买, 无优惠券'); } else { console.log('手机库存不足'); } };
接下来需要把函数包装进职责链节点,我们定义一个构造函数 Chain
,在 new Chain
的时候传递的参数即为需要被包装的函数,同时它还拥有一个实例属性 this.successor
,表示在链中的下一个节点。
var Chain = function (fn) { this.fn = fn; this.successor = null; }; // 指定在链中的下一个节点 Chain.prototype.setNextSuccessor = function (successor) { return this.successor = successor; }; // 传递请求给某个节点 Chain.prototype.passRequest = function () { var ret = this.fn.apply(this, arguments); if (ret === 'nextSuccessor') { return this.successor && this.successor.passRequest.apply(this.successor, arguments); } return ret; };
接下来,把3个订单函数分别包装成职责链的节点:
var chainOrder500 = new Chain(order500); var chainOrder200 = new Chain(order200); var chainOrderNormal = new Chain(orderNormal);
然后指定节点在职责链中的顺序:
chainOrder500.setNextSuccessor(chainOrder200); chainOrder200.setNextSuccessor(chainOrderNormal);
最后把请求传递给第一个节点:
chainOrder500.passRequest(1, true, 500);// 输出:500 元定金预购,得到 100 优惠券 chainOrder500.passRequest(2, true, 500);// 输出:200 元定金预购,得到 50 优惠券 chainOrder500.passRequest(3, true, 500);// 输出:普通购买,无优惠券 chainOrder500.passRequest(1, false, 0);// 输出:手机库存不足
通过改进,我们可以自由灵活地增加、移除和修改链中的节点顺序,假设某天需要支持 300 元定金购买,可以在该链中增加一个节点即可:
var order300 = function () { // 具体实现略 }; chainOrder300 = new Chain(order300); chainOrder500.setNextSuccessor(chainOrder300); chainOrder300.setNextSuccessor(chainOrder200);