Decoupling is one of the
prominent mantras in software engineering.
Chain of responsibility helps to decouple sender
of a request and receiver of the request with some trade-offs.
Chain of responsibility is a design pattern
where a sender sends a request to a chain of objects, where the objects in the
chain decide themselves who to honor the request. If an object in the chain decides
not to serve the request, it forwards the request to the next object in the
chain.
In a chain of objects, the responsibility of
deciding who to serve the request is left to the objects participating in the
chains.
รจIt is
similar to ‘passing the question in a quiz scenario’. When the quiz master asks
a question to a person, if he doesn’t knows the answer, he passes the question
to next person and so on. When one person answers the question, the passing
flow stops. Sometimes, the passing might reach the last person and still nobody
gives the answer.
Currency.java
public class Currency {
private int
amount;
public Currency(int
amt){
this.amount = amt;
}
public int
getAmount(){
return this.amount;
}
}
DispenseChain.java
public interface DispenseChain {
void
setNextChain(DispenseChain nextChain);
void dispense(Currency cur);
}
Rupees1000Dispenser.java
public class Rupees1000Dispenser implements DispenseChain {
private DispenseChain chain;
@Override
public void
setNextChain(DispenseChain nextChain) {
this.chain=nextChain;
}
@Override
public void
dispense(Currency cur) {
if(cur.getAmount() >=
1000){
int num = cur.getAmount()/1000;
int remainder = cur.getAmount() % 1000;
System.out.println("Dispensing "+num+" Rs. 1000 note");
if(remainder !=0) this.chain.dispense(new
Currency(remainder));
} else {
this.chain.dispense(cur);
}
}
}
Rupees500Dispenser.java
public class Rupees500Dispenser implements DispenseChain{
private DispenseChain chain;
@Override
public void
setNextChain(DispenseChain nextChain) {
this.chain=nextChain;
}
@Override
public void
dispense(Currency cur) {
if(cur.getAmount() >=
500){
int num = cur.getAmount()/500;
int remainder = cur.getAmount() % 500;
System.out.println("Dispensing "+num+" Rs. 500 note");
if(remainder !=0) this.chain.dispense(new
Currency(remainder));
} else {
this.chain.dispense(cur);
}
}
}
Rupees100Dispenser.java
public class Rupees100Dispenser implements DispenseChain {
private DispenseChain chain;
@Override
public void
setNextChain(DispenseChain nextChain) {
this.chain=nextChain;
}
@Override
public void
dispense(Currency cur) {
if(cur.getAmount() >=
100) {
int num = cur.getAmount()/100;
int remainder = cur.getAmount() % 100;
System.out.println("Dispensing "+num+" Rs. 100 note");
if(remainder !=0) this.chain.dispense(new
Currency(remainder));
} else {
this.chain.dispense(cur);
}
}
}
ATMDispenseChain.java
public class
ATMDispenseChain {
private
DispenseChain chainStart;
public
ATMDispenseChain() {
// initialize the chain
this.chainStart = new Rupees1000Dispenser();
DispenseChain chain500 = new Rupees500Dispenser();
DispenseChain chain100 = new Rupees100Dispenser();
// set the chain of responsibility
chainStart.setNextChain(chain500);
chain500.setNextChain(chain100);
}
public
DispenseChain getChainStart() {
return chainStart;
}
}
TestChainPattern.java
import
java.util.Scanner;
public class
TestChainPattern {
public static void
main(String[] args) {
ATMDispenseChain atmDispenser = new ATMDispenseChain();
int amount = 0;
System.out.println("Enter amount to dispense");
Scanner input = new Scanner(System.in);
amount = input.nextInt();
if (amount % 100 != 0) {
System.out.println("Amount should be in multiple of 100s.");
return;
}
// process the request
atmDispenser.getChainStart().dispense(new Currency(amount));
input.close();
}
}
Chain of Responsibility Pattern Examples
ATM dispense machine.
Struts interceptor.
Usage of Chain of Responsibility Pattern in JDK
java.util.logging.Logger#log()
javax.servlet.Filter#doFilter()