职责链模式的基础
定义:职责链模式(Chain of responsibility)是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。职责链模式的名字非常形象,一系列可能会处理请求的对象被该连接成一条链,请求在这些对象之间依次传递,直到遇到一个可以处理它的对象,我们把这些对象成为链中的节点。
优点:请求发送者只需要知道链中的第一个节点,从而弱化了发送者和一组接收者之间的强联系。
使用场景:挤公交车递钱(只有售票员可以收钱)、交押金预定手机
例子
假设一个电视购物网站对于某部新上市的手机经过了2轮缴纳500元定金与200元定金的预定,现在已经到了正式购买的阶段。
支付了500元定金的用户在购买阶段可以使用100元优惠券,200元定金可以使用50元优惠券,普通用户没有优惠且当库存不足不一定能买到。
orderType: 表示订单类型(定金或者普通用户),code的值为1时候是500元定金用户,为2是200元定金用户,为3则是普通用户。
pay : 表示用户是否支付定金,用户虽然下过500元定金的订单但是如果他一直没有支付定金,那么只能降级为普通用户。
stock : 仅用户普通用户的库存数量,定金用户不受限制。
简洁版:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30// 500 order
var order500 = function (orderType,pay,stock) {
if(orderType === 1 && pay === true){
console.log('500 rmb deposit, get 100 coupon ')
} else {
order100(orderType,pay,stock) // req pass to 200 order
}
};
var order200 = function (orderType,pay,stock) {
if(orderType === 2 && pay === true){
console.log('200 rmb deposit , get 50 coupon')
} else{
orderNormal(orderType,pay,stock)
}
};
var orderNormal = function (orderType,pay,stock) {
if(stock > 0){
console.log('normal buy no coupon')
} else{
console.log('the stock lack')
}
};
//test result:
order500(1,true,500);
order500(2,true,500);
order500(3,true,500);
order500(1,false,500);
现在已经基本符合了职责链模式定义,下面实现灵活可拆分的职责链模式,我的意思就是不要像上述那样面向过程的从500传递到200然后再到普通,万一我们想传递到100呢? 岂不是还得要大修一番?
职责链模式重构1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63// 500 order
var order500 = function (orderType,pay,stock) {
if(orderType === 1 && pay === true){
console.log('500 rmb deposit, get 100 coupon ')
} else {
return 'nextSuccessor' // unknow the next node but always pass to next.
}
};
var order200 = function (orderType,pay,stock) {
if(orderType === 2 && pay === true){
console.log('200 rmb deposit , get 50 coupon')
} else{
return 'nextSuccessor';
}
};
var orderNormal = function (orderType,pay,stock) {
if(stock > 0){
console.log('normal buy no coupon')
} else{
console.log('the stock lack')
}
};
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)
//最后把请求传递给第一个节点
//test
chainOrder500.passRequest(1,true,500);
chainOrder500.passRequest(2,true,500);
//通过改进,我们可以自由灵活的增加移除和链中的节点顺序,假如我们 又想支持
//300元定金购买,那我们就在改链中增加一个节点即可:
var order300 = function () {
// todo
};
chainOrder300 = new Chain(chainOrder300)
chainOrder500.setNextSuccessor(chainOrder300)
chainOrder300.setNextSuccessor(chainOrder200)
我们可以自由灵活的增加移除和链中的节点顺序,这样就很简单能满足瞬息万变的需求了。