js的设计模式-责任链模式

需求

嗨老伙计,我这里有一台ATM取款机,它需要一个正确的程序来为用户提供纸币取款服务,比如:用户需要取出186元,那么取款机需要分别吐出,100元、50元、20元、10元、5元、1元各一张


js的设计模式-责任链模式_第1张图片
chain_of_responsibility_atm.png

分析

看了这个需求,有木有一道灵光从天灵盖直射前额叶...

没有什么不是一个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/

你可能感兴趣的:(js的设计模式-责任链模式)