Chain of Responsibility Design Pattern in Java

Type : Behavioral Design Pattern

Summary


Chain of Responsibility deals with how best we can design a sender - receivers without tight coupling the sender and receivers. Where the sender
sends an object to a set of receivers. And one or more than one receiver work on the object that the sender sent.

Details

As the name suggests, rather than the Client deciding how to process an request object( Say by calling specific method from specific Object), the request is sent though a pipe or chain of different Objects which might be able to process the request.

The request enters from one end and pass on the request to the next Handler until the request processor is done.

Following are the participants in this pattern
Handler : An Interface that Concrete Handlers implements
Concrete Handler : Handler implementation that processes the request, or pass to the next handler in the chain.
Client : Client that utilizes the chain of handlers by invoking first handler.

Advantages

Sender and receiver (handler) can go independently
Follows plug in like architecture, where we can add more handler without changing existing behaviour.
Easy to maintenance and more testable code. 

Disadvantages

If the handlers are not implemented properly it could result in broken processing the request.
Based on the logic wrong order of the Handler in the chain could cause issue.

Example 

Let's take example of a software system which processes customer request. Broadly we have divided the customer request as of 3 types for now Account, Billing and Technical support related. When client sends the request we loop though all the respective handler and process the request. We also have a Default handler which works when the customer that is asking for something we donot support.

Class Diagram



Sample Code 



// interface to represent a request
public interface Request {

  public String [] getRequestDetails(); //PasswordReset, UnlockAccount, GetAccountDetails
  
  public void setRequestDetails(String [] news); //PasswordReset, UnlockAccount, GetAccountDetails
}

// customer support request object containging request details
public class CustomerSupportRequest implements Request {

  private String[] requestDetails;

  public CustomerSupportRequest(String[] reqType) {
    this.requestDetails = reqType;
  }

}

// abstract request handler
public abstract class RequestHandler {

  RequestHandler nextHandler;

  public void setNextHandler(RequestHandler handler) {
    this.nextHandler = handler;
  }

  public void handleRequest(Request req) {
    processRequest(req);
    if (this.nextHandler != null) {
      this.nextHandler.handleRequest(req);
    }
  }

  public abstract void processRequest(Request req);
  
}


// account related request handler
public class AccountRequestHandler extends RequestHandler {

  @Override
  public void processRequest(Request req) {
    System.out.println("ACCOUNT DEPARTMENT HANDLED!");
  }

}

//billing related request handler
public class BillingRequestHandler extends RequestHandler {

  @Override
  public void processRequest(Request req) {

    System.out.println("BILLING DEPARTMENT HANDLED!");

  }

}

//technical related request handler
public class TechnicalRequestHandler extends RequestHandler {

  @Override
  public void processRequest(Request req) {
   
    System.out.println("TECH DEPARTMENT HANDLED!");
    
  }

}

Comments

Popular posts from this blog

Converting Java Map to String

Difference between volatile and synchronized

Invoking EJB deployed on a remote machine