Sunday, June 26, 2016

the Chain of Responsibility design pattern

The chain of responsibility is a fairly easy to use design pattern. Its main goal is to allow several objects to collaborate in order to solve a problem. Each object knows what it can do, and if the request does not fall into its scope of responsabilty, the objects passes it to the next one, and so on. The rationale behind using this pattern is to enforce separation of concerns and decouple a problem smaller sub-problems to make it easier to solve.

An analogy that might help understanding the pattern is when you call the customer support for your phone operator. When you call the support, you are asked about the category of your request, and then you are dispatched to the agent who has the skills to handle your request. If the agent sees that your request needs another set of skills, he forwards it to another agent, and so on until your request is fullfilled.

In this tutorial, we are going to implement the chain of responsability based on the example above.

First of all, we need an interface (or abstract class) that will constisturte the building block of our chain. Each object that implements the interface will either process the request or forwards it to the next object.

public interface RequestHandler {
 
 public void process(Request request);
 
 public void setNext(RequestHandler handler);

}
Next we need to define the handlers that implements our interface.

public class SecurityRequestHandler implements RequestHandler {
 
 RequestHandler nextHandler;

 @Override
 public void process(Request request) {
  // TODO Auto-generated method stub
  if(request.getCriticityLevel() == CriticityLevel.SECURITY){
   System.out.println("Your request" + request.description + " is being handled by the security departement");
  }else if (nextHandler != null){
   System.out.println("Your request is being forwarded to another departement");
   nextHandler.process(request);
  }
  
 }

 @Override
 public void setNext(RequestHandler handler) {
  // TODO Auto-generated method stub
  this.nextHandler = handler;
  
 }
public class InfrastructureRequestHandler implements RequestHandler {
 
 RequestHandler nextHandler;

 @Override
 public void process(Request request) {
  // TODO Auto-generated method stub
  if(request.getCriticityLevel() == CriticityLevel.INFRACSTRUCTURE ){
   System.out.println("Your request: " + request.description + " is being handled by the financial departement");
   }else if (nextHandler != null){
    System.out.println("Your request is being forwarded to another departement");
    nextHandler.process(request);
   }
 }

 @Override
 public void setNext(RequestHandler handler) {
  // TODO Auto-generated method stub
  this.nextHandler = handler;
  
 }

}


public class FinancialRequestHandler implements RequestHandler {
 
 RequestHandler nextHandler;

 @Override
 public void process(Request request) {
  // TODO Auto-generated method stub
  if(request.getCriticityLevel() == CriticityLevel.FINANCIAL ){
  System.out.println("Your request " + request.description + " is being handled by the financial departement");
  }else if (nextHandler != null){
   System.out.println("Your request is being forwarded to another departement");
   nextHandler.process(request);
  }
  
 }

 @Override
 public void setNext(RequestHandler handler) {
  // TODO Auto-generated method stub
  this.nextHandler = handler;
  
 }

}
For illustration purposes the Request POJO looks like:


public class Request {
 
 String description;
 
 int criticityLevel;
 
 public Request(String description, int clearanceLevel) {
  this.description = description;
  this.criticityLevel = clearanceLevel;
 }

 public String getDescription() {
  return description;
 }

 public int getCriticityLevel() {
  return criticityLevel;
 }

}
Finally, we can chain our handlers according to their level of responsibility.

public class Main {
 
 public static void main(String[] args){
  
  RequestHandler handler1 = new SecurityRequestHandler();
  RequestHandler handler2 = new InfrastructureRequestHandler();
  RequestHandler handler3 = new FinancialRequestHandler();
  
  
  
  handler1.setNext(handler2);
  handler2.setNext(handler3);
  
  Request request = new Request("Error in the last month bill", CriticityLevel.FINANCIAL);
  Request request2 = new Request("Poor network coverage", CriticityLevel.INFRACSTRUCTURE);
  
  System.out.println("--------------Request1");
  handler1.process(request);
  
  System.out.println("--------------Request2");
  handler1.process(request2);
  
  
  
 }

}
Result:






No comments:

Post a Comment