Chain of Responsibility — Behavioral Design Pattern

responsibility chain

When we think about chain of responsibility, it gives some understanding or feeling about what it does or what it suppose to do by it self. But for easiness, will map this into a real world scenario where it’s used in common day to day activities in your company or organization.

Some of you may heard about “chain of command”. Which used in many management structures to split responsibilities among colleagues or co-workers in an organization. By this the organization’s hierarchy is set from the bottom to the top, where who must answer to whom and what type of accountabilities, authorities and decision making powers they get when performing day to day activities.

So, Now you may have some idea about a real world use of the pattern in different domain, other than the programming.

If we move back to our title, the “chain of responsibility” pattern in software designing.

  • Decoupling the initiator and receiver
  • Runtime process picking strategy

are the main key points of this design pattern. In each responsibility chain object, based on certain criterions different actions are performed.

Let’s think about an example

In Spring world, the servlet filters are commonly used for pre-request and post-request processing. In those situations, the framework gives flexibility to write our own filter and place in the filter chain to do the processing. That is a classic example of chain of responsibility in action.

@Component
public class TestFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("Host : {}", request.getRemoteHost());
log.info("Remote : {}", request.getRemoteAddr());
chain.doFilter(request, response); // call the next filter
}
}

Code Example

We’ll take a sample scenario of a cloud partner monthly bill calculation process. In that case, for a customer there can be multiple sub-cloud providers and services in use. for that, the agent partner should bill under one invoice. So, the bill processing logic in a software design level would be like this.

The following program is a JAVA console based application.

  1. Create Bill entity.
public class Bill {

private double awsCost;
private double gCloudCost;
private double azureCost;
private double subTotal;
private double discount;
private double total;

...
}

2. The base Handler interface for bill processing.

public interface Handler {

/**
* The next handler reference
*
*
@param handler - the handler
*/
void nextHandler(Handler handler);

/**
* The bill processor
*
*
@param bill - the bill entity
*/
void process(Bill bill);
}

3. Create individual handlers for each process. Ex : AWSHandler

/**
* AWS related cost handler
*/
public class AWSHandler implements Handler {

private Handler next;

@Override
public void nextHandler(Handler handler) {
next = handler;
}

@Override
public void process(Bill bill) {
// do the AWS cost calculations
bill.setAwsCost(1000);
System.out.println("AWSHandler : done");
// call the next handler
if (next != null) {
next.process(bill);
}
}
}

4. The main initiator would be like.

public class Main {

public static void main(String[] args) {
Bill hostingBill = new Bill();

// create handlers
AWSHandler awsHandler = new AWSHandler();
GCloudHandler gCloudHandler = new GCloudHandler();
AzureHandler azureHandler = new AzureHandler();
DiscountHandler discountHandler = new DiscountHandler();

// set next hop handlers
awsHandler.nextHandler(gCloudHandler);
gCloudHandler.nextHandler(azureHandler);
azureHandler.nextHandler(discountHandler);

// trigger the calculation
awsHandler.process(hostingBill);

System.out.println("--------------------------------");
System.out.println("Monthly Hosting Bill");
System.out.println("--------------------------------");
System.out.println("AWS Cost : " + hostingBill.getAwsCost());
System.out.println("Google Cloud Cost : " + hostingBill.getGCloudCost());
System.out.println("Azure Cost : " + hostingBill.getAzureCost());
System.out.println("--------------------------------");
System.out.println("Sub Total : " + hostingBill.getSubTotal());
System.out.println("Discount : " + hostingBill.getDiscount());
System.out.println("Total : " + hostingBill.getTotal());
}
}

The application’s console output.

AWSHandler : done
GCloudHandler : done
AzureHandler : done
DiscountHandler : done
--------------------------------
Monthly Hosting Bill
--------------------------------
AWS Cost : 1000.0
Google Cloud Cost : 1500.0
Azure Cost : 2500.0
--------------------------------
Sub Total : 5000.0
Discount : 250.0
Total : 4750.0

Here’s the link for the source code.

I hope you liked it and got clear understanding about the chain of responsibility design pattern.

Thanks for reading !!…

Full Stack Engineer

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

My Experience in LGMSOC’21

How I Made My Shitty Python Code 20 Times Faster

Jeep Wrangler Parts by ExtremeTerrain

Building a Dockerized Cloudera Pseudo Cluster, aka testing the Big Data ecosystem when you have no…

Installing your own Git server on Raspberry Pi 4 using GitLab CE

How to build complex Forge apps using Custom UI

How to perform Google search with Python

AWS re:Invent 2020 Guide — How to Make The Most of The Virtual Event

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Buwaneka Boralessa

Buwaneka Boralessa

Full Stack Engineer

More from Medium

Read, Write and Delete Operations for S3 Bucket using Spring boot

Who Shot Rest? Let’s Discover gRPC

Keep it Simple: dev and test environments with docker compose and Testcontainers

Unit Testing Apache Camel