需求
嗨老伙计,我这里有一台ATM取款机,它需要一个正确的程序来为用户提供纸币取款服务,比如:用户需要取出186元,那么取款机需要分别吐出,100元、50元、20元、10元、5元、1元各一张
分析
看了这个需求,有木有一道灵光从天灵盖直射前额叶...
没有什么不是一个
if
搞定不了的,如果有,那就俩if
是哎,手枪能治疗癌症这种事情我会乱说?我们决定用一个听起来高大上的模式来解决这个需求---责任链模式
实现
var MoneyStack = function(billSize) {
this.billSize = billSize;
this.next = null;
}
MoneyStack.prototype = {
withdraw: function(amount) {
var numOfBills = Math.floor(amount / this.billSize);
if (numOfBills > 0) {
// Eject the bills
this._ejectMoney(numOfBill);
// Shrink the amount by how much money we ejected
amount = amount - (this.billSize * numOfBills);
}
// If there is any money left to withdraw and if we have
// another stack in the line, pass the request on
amount > 0 && this.next && this.next.withdraw(amount);
},
// set the stack that comes next in the chain
setNextStack: function(stack) {
this.next = stack;
},
// private method that ejects the money
_ejectMoney: function(numOfBills) {
console.log(numOfBills + " $" + this.billSize
+ " bill(s) has/have been spit out");
}
}
通过这样的方法使用这个对象
var ATM = function() {
// Create the stacks of money
// We'll show you the implementation for this next
var stack100 = new MoneyStack(100),
stack50 = new MoneyStack(50),
stack20 = new MoneyStack(20),
stack10 = new MoneyStack(10),
stack5 = new MoneyStack(5),
stack1 = new MoneyStack(1);
// Set the hierarchy for the stacks
stack100.setNextStack(stack50);
stack50.setNextStack(stack20);
stack20.setNextStack(stack10);
stack10.setNextStack(stack5);
stack5.setNextStack(stack1);
// Set the top stack as a property
this.moneyStacks = stack100;
}
ATM.prototype.withdraw = function(amount) {
this.moneyStacks.withdraw(amount);
}
// USAGE
var atm = new ATM();
atm.withdraw(186);
/* outputs:
1 $100 bill(s) has/have been spit out
1 $50 bill(s) has/have been spit out
1 $20 bill(s) has/have been spit out
1 $10 bill(s) has/have been spit out
1 $5 bill(s) has/have been spit out
1 $1 bill(s) has/have been spit out
*/
atm.withdraw(72);
/* outputs:
1 $50 bill(s) has/have been spit out
1 $20 bill(s) has/have been spit out
2 $1 bill(s) has/have been spit out
*/
上面代码封装了一个ATM
类,并且暴露了withdraw()
方法
// ...
stack100.setNextStack(stack50);
stack50.setNextStack(stack20);
stack20.setNextStack(stack10);
stack10.setNextStack(stack5);
stack5.setNextStack(stack1);
// ...
这段代码很简单,就是按照指定顺序,将100元、50元...按照顺序码放整齐,俨然一个链条
// ...
ATM.prototype.withdraw = function(amount) {
this.moneyStacks.withdraw(amount);
}
// ...
stack100.setNextStack(stack50);
// ...
这段代码定义了ATM“吐钱”逻辑的入口,执行withdraw()
方法会尝试将链顶层的货币“吐”给用户
好了,我们开始取钱吧
var ATM = function() {
// ...
this.moneyStacks = stack100;
// ...
}
ATM对象取钱时,将从100元开始,如果金额不足以取到100元,那么通过
// ...
amount > 0 && this.next && this.next.withdraw(amount);
// ...
调用链的下一级(50),再调用下下级(20)...
原文链接:https://www.joezimjs.com/javascript/javascript-design-patterns-chain-of-responsibility/