Chain of Responsibility Pattern - Walking Techie

Blog about Java programming, Design Pattern, and Data Structure.

Monday, August 1, 2016

Chain of Responsibility Pattern

Chain of responsibility is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain. A mechanism also exists for adding new processing objects to the end of this chain.

In simple way, chain of responsibility pattern creates a chain of receiver object for a request. This pattern decouple sender and receiver of request based on type of object. This pattern comes under behavioral design pattern.

Lets, understand this pattern with real world scenario.

In corporate office, company provide some facility to their employees to claim expenses on particular usages like internet, corporate travel etc. Employee pays bill for these expenses themselves, after that employee reimburse expense from company. When Employee claims the expense, these expense request goes to their manager for approval, if this claim amount limit comes under manager's approval limit then he/she will approve it, otherwise request will be transferred to his/her manager. If it is not also his/her limits then it will passed to the next higher level manager.

Implementation

We have different roles, each having a fixed purchasing limit and a successor. Every time a user in a role receives a purchase request that exceeds his or her limit, the request is passed to his or her successor. We are going to create PurchasePower abstract class with abstract method processRequest and concrete classes extending this abstract class. We will have created PurchaseRequest class that keeps purchase data.

UML:

Chain of Responsibility Pattern UML

Step 1

Create an abstract class PurchasePower.

public abstract class PurchasePower {
 protected PurchasePower successor;
 protected static final double BASE = 500;

 abstract protected double getAllowable();

 abstract protected String getRole();

 public void setSuccessor(PurchasePower successor) {
  this.successor = successor;
 }

 public void processRequest(PurchaseRequest request) {
  if (request.getAmount() < getAllowable()) {
   System.out.println(getRole() + " will approve $"
     + request.getAmount());
  } else if (successor != null) {
   successor.processRequest(request);
  }
 }
}

Step 2

Create an concrete classes that extends PurchasePower class.

public class Manager extends PurchasePower {

 @Override
 protected double getAllowable() {
  return BASE * 10;
 }

 @Override
 protected String getRole() {
  return "Manager";
 }
}
public class Director extends PurchasePower {

 @Override
 protected double getAllowable() {
  return BASE * 20;
 }

 @Override
 protected String getRole() {
  return "Director";
 }
}
public class VicePresident extends PurchasePower {

 @Override
 protected double getAllowable() {
  return BASE * 40;
 }

 @Override
 protected String getRole() {
  return "Vice President";
 }
}
public class President extends PurchasePower {

 @Override
 protected double getAllowable() {
  return BASE * 60;
 }

 @Override
 protected String getRole() {
  return "President";
 }
}

Step 3

Create PurchaseRequest class that will have purchase data.

public class PurchaseRequest {
 private double amount;
 private String purpose;

 public PurchaseRequest(double amount, String purpose) {
  this.amount = amount;
  this.purpose = purpose;
 }

 public double getAmount() {
  return amount;
 }

 public void setAmount(double amount) {
  this.amount = amount;
 }

 public String getPurpose() {
  return purpose;
 }

 public void setPurpose(String purpose) {
  this.purpose = purpose;
 }
}

Step 4

Create CheckAuthority class that will test chain of responsibility pattern.

import java.io.InputStreamReader;

public class CheckAuthority {

 public static void main(String[] args) {
  PurchasePower manager = new Manager();
  PurchasePower director = new Director();
  PurchasePower vicePresident = new VicePresident();
  PurchasePower president = new President();

  manager.setSuccessor(director);
  director.setSuccessor(vicePresident);
  vicePresident.setSuccessor(president);
  // press Ctrl + c to end
  try {
   while (true) {
    System.out
     .println("Enter the amount to check who should approve your expenditure.");
    System.out.print(">");
    double d = Double.parseDouble(new BufferedReader(
      new InputStreamReader(System.in)).readLine());
    manager.processRequest(new PurchaseRequest(d, "General"));
   }
  } catch (Exception e) {
   System.exit(1);
  }
 }
}

Output of the above program shown below.

Enter the amount to check who should approve your expenditure.
>1000
Manager will approve $1000.0
Enter the amount to check who should approve your expenditure.
>2000
Manager will approve $2000.0
Enter the amount to check who should approve your expenditure.
>4000
Manager will approve $4000.0
Enter the amount to check who should approve your expenditure.
>5000
Director will approve $5000.0
Enter the amount to check who should approve your expenditure.
>10000
Vice President will approve $10000.0
Enter the amount to check who should approve your expenditure.
>20000
President will approve $20000.0
Enter the amount to check who should approve your expenditure.
>25000
President will approve $25000.0
Enter the amount to check who should approve your expenditure.

Important Point

  1. The base class maintains a "next" pointer.
  2. Each derived class implements its contribution for handling the request.
  3. If the request needs to be "passed on", then the derived class "calls back" to the base class, which delegates to the "next" pointer.
  4. The client (or some third party) creates and links the chain (which may include a link from the last node to the root node).
  5. The client "launches and leaves" each request with the root of the chain.
  6. Recursive delegation produces the illusion of magic.

Reference: https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern

1 comment :

  1. factorial hundred In the last few days, the “factorial of 100” is one of the top subjects and a lot of maths geeks compute it using voice assistants such as Alexa, Shiri, etc.
    factorial hundred In the last few days, the “factorial of 100” is one of the top subjects and a lot of maths geeks compute it using voice assistants such as Alexa, Shiri, etc.
    factorial hundred In the last few days, the “factorial of 100” is one of the top subjects and a lot of maths geeks compute it using voice assistants such as Alexa, Shiri, etc.


    ReplyDelete