职责链模式: 将多个接收者串成一条链子的形式,让请求的对象在该条链子上被传送,直到某个对象可以处理。
场景是在对象发送出时,有多个接收者可以处理该发送者的请求,一般在业务中会经常遇到一个场景,点击某个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函数,只需新增一个节点,并修改下顺序即可,并且可以一目了然的看清这些节点之间的顺序和数量。