Programming codex

Chain of Responsibility JavaScript Design Pattern

[ad_1]

Today, we’ll be talking about the Chain of Responsibility Pattern. This pattern decouples the sender and receiver of requests. This is done with a chain of objects that can each handle the request itself or pass it on to the next object. Confused? Read on.

Chain of Responsibility Structure

3 parts make up the Chain of Responsibility pattern: sender, receiver, and request. The sender makes requests. The receiver is a chain of 1 or more objects that choose whether to handle the request or pass it on. The request itself can be an object that encapsulates all the appropriate data, or it could just be a normal function call on the receiver with no arguments.

Senders send the request to the first receiver object in the chain. The sender only knows about this first part of the chain and nothing about the other receivers. The first receiver either handles the request or passes it on to the next receiver in the chain. Each receiver only knows about the next receiver in the line. The request will continue down the line until the request was handled or there are no more receivers to pass it on to, at which point either an error is thrown or nothing happens, depending on how you design your chain.

Chain of Responsibility Example

For our example, we’ll be creating an ATM. The chain is going to consist of different sized dollar bills. When you ask for some cash, the machine starts at the larger bills and pulls out as many of those that it needs, then moves on to the next smaller bill and so on until we’ve got all of the money or we run out of bills. This example is purposefully simple, because that helps to show the concept more clearly without diluting the code with too many example-specific implementations.

We’ll start by creating the receiver ‘class’: MoneyStacks. Normally this would just be an interface that would be implemented by different receivers, but this example is simple enough that the only variance between each of the receivers will be the size of the bills in the stack. We’ll just set that number via a parameter in the constructor.


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(numOfBills) {
console.log(numOfBills + " $" + this.billSize
+ " bill(s) has/have been spit out");
}
}

The math behind it is pretty simple. The withdraw function is what uses the chaining ability by ejecting the required bills and then passing the request on to the next in the chain when appropriate.

Now, we’ll build the ATM. Its constructor instantiates all of the money stacks and puts them into their hierarchical order. When someone calls the withdraw method on it, it the responsibility of withdrawing gets passed on to the chain of money stacks.


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
*/

Ending My Responsibilities

That’s all there is to this pattern. It’s pretty simple. Like the Command and Observer patterns, its purpose is to decouple the sender from the receivers but for different reasons and with different trade-offs. Due to its hierarchical structure, it’s also similar to the Composite pattern, and can even be injected within the Composite pattern for some real fun.

[ad_2]

Source by Joe J Zim

Share on facebook
Share on google
Share on twitter
Share on linkedin
Share on pinterest
Share on whatsapp

Leave a comment

Your email address will not be published. Required fields are marked *

Search:

Topics

Recent Posts