职责链模式
特点
- 一步操作可能分为多个职责角色来完成
- 把这些角色都分开,然后用一个链串起来
- 将发起者和各个处理者隔离
介绍
- 对于一个任务,发起者的状态不同它的执行过程也不尽相同。正常情况下需要我们在一个请求函数的开头进行多重判断对于我们一个具体的业务函数中,添加很多不必要的判断条件是没有意义而且后期修改难以维护。
- 因此,提出职责链模式,将满足同一个业务的不同分支首先进行拆分。然后由一个统一的入口开始,满足当前就执行,不满足就沿着职责连进入下一个分支。在代码上精简了判断条件的复合,对外也只有一个入口。
- 在后期维护时也更加简单,只需要在需要的地方见链解开,把自己的一个判断条件添加进去就行,能够保证在最大限度的对原有代码不进行破坏。(联想 数据结构->链表)
demo
更多详细代码
/**
* 如下:假设某商店预售某商品,
* 用户交付定金500元后会有100元的优惠券,不受库存数量限制
* 用户交付定金100元后会有50元的优惠券,不受库存数量限制
* 不交付定金的为普通用户,受库存数量限制
* 若库存数量少于10时,普通用户不可购买
* 若用户下了定金的订单但是并没有交付定金则降级为普通用户
*/
/*--- 定义商店对象 ---*/
var shop = {
total: 10, //商店仅剩10件商品
};
/*--- 定义有500元的定金的处理方法 ---*/
var order500 = function (user) {
if (user.ordertype == 1 && user.pay == true) {
console.log(user.name + ":已交付500元定金,获得100元定金");
} else {
return "nextSuccessor";
}
};
var order200 = function (user) {
if (user.ordertype == 2 && user.pay == true) {
console.log(user.name + ":已交付100元定金,获得50元定金");
} else {
return "nextSuccessor";
}
};
var nomal = function (user) {
if (shop.total > 10) {
console.log(user.name + ":购买手机成功!");
} else {
console.log(user.name + ":手机库存不足");
}
};
/*--- 职责链节点工厂 ---*/
var Chain = function (fn) {
this.fn = fn;
this.successor = null;
};
Chain.prototype.setNextSuccessor = function (successor) {
this.successor = successor;
};
Chain.prototype.passRequset = function () {
var ret = this.fn.apply(this, arguments);
if (ret === "nextSuccessor") {
return (
this.successor &&
this.successor.passRequset.apply(this.successor, arguments)
);
}
return ret;
};
/*--- 构造职责链节点 ---*/
var chainOrder500 = new Chain(order500);
var chainOrder200 = new Chain(order200);
var chainNomal = new Chain(nomal);
/*--- 构造职责链 ---*/
chainOrder500.setNextSuccessor(chainOrder200);
chainOrder200.setNextSuccessor(chainNomal);
/*--- 构造购买者 ---*/
var user1 = { ordertype: 1, pay: true, name: "Tim" };
var user2 = { ordertype: 1, pay: false, name: "Salary" };
var user3 = { ordertype: 2, pay: true, name: "Bob" };
var user4 = { ordertype: nomal, pay: false, name: "Mz" };
/*--- 测试 ---*/
console.log("-------交付定金500");
chainOrder500.passRequset(user1);
console.log("-------下定金订单,未交付定金");
chainOrder500.passRequset(user2);
console.log("-------交付定金200");
chainOrder500.passRequset(user3);
console.log("-------未交付定金");
chainOrder500.passRequset(user4);