JavaScript职责链模式

职责链模式:

将多个接收者串成一条链子的形式,让请求的对象在该条链子上被传送,直到某个对象可以处理。

场景是在对象发送出时,有多个接收者可以处理该发送者的请求,一般在业务中会经常遇到一个场景,点击某个button以后,比如投资,第一个条件是否实名过,如果未实名,则提示需实名,第二个条件是如果已经实名,当余额不足时,弹出dialog让去充值,第三个条件是当余额充足时,是否已经测评过,如果未测评,则弹出dialog需测评。当这3个条件都满足时,最后去请求投资。

如果我们一般的编写代码则是,

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
var autonym = function(user) {
if(!user.hasAuth) {
console.log('need auth');
return;
} else {
recharge(user);
}
};

var recharge = function(user) {
if(!user.amountNoMeet) {
console.log('need recharge');
return;
} else {
survey(user);
}
};

var survey = function(user) {
if(!user.hasSurvey) {
console.log('need survey');
return;
} else {
gotoInvest();
}
}

var gotoInvest = function() {
console.log('invest success!');
};

通常对于一系列的判断条件我们会如上这样写,这样写弊端是当这三个条件中增加一个判断条件,比如是否余额充足后再判断投资额度是否还有,那么我们就需要去修改recharge函数,并新增一个函数,这样就相当于把原来的链子砍断,然后再新增一个节点并和前后连接起来,维护起来很麻烦。

那我们采取职责链模式写法改进如下:

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
var autonym = function(user) {
if(!user.hasAuth) {
console.log('need auth');
return;
} else {
return 'next';
}
};

var recharge = function(user) {
if(!user.amountNoMeet) {
console.log('need recharge');
return;
} else {
return 'next';
}
};

var survey = function(user) {
if(!user.hasSurvey) {
console.log('need survey');
return;
} else {
return 'next';
}
};

var gotoInvest = function() {
console.log('invest success!');
};

class Chain {
constructor(fn) {
this.fn = fn;
this.next = null;
}

setNextProcessor(next) {
this.next = next;
}

handleRequest() {
var rt = this.fn.apply(this, arguments);
if(rt === 'next') {
return this.next && this.next.handleRequest.apply(this.next, arguments);
}
return rt;
}
}

var autonymChain = new Chain(autonym);
var rechargeChain = new Chain(recharge);
var surveyChain = new Chain(survey);
var gotoInvestChain = new Chain(gotoInvest);

autonymChain.setNextProcessor(rechargeChain);
rechargeChain.setNextProcessor(surveyChain);
surveyChain.setNextProcessor(gotoInvestChain);

autonymChain.handleRequest({hasAuth: true, amountNoMeet: true, hasSurvey: false});

上面代码输出need survey,如果再新增一个条件余额充足后再判断投资额度是否还有,则:

1
2
3
4
5
6
7
8
9
10
11
12
13
var amountLimit = function(user) {
if(user.amountLimit) {
console.log('amount limit');
return;
} else {
return 'next';
}
}
var amountLimitChain = new Chain(amountLimit);

rechargeChain.setNextProcessor(amountLimitChain);
amountLimitChain.setNextProcessor(surveyChain);

这样就无需修改recharge函数,只需新增一个节点,并修改下顺序即可,并且可以一目了然的看清这些节点之间的顺序和数量。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!