Tuesday, 15 October 2013

Chain of Responsibility Design pattern - Implementation(One or more Rece...

🚀 Master Java Design Patterns & Software Architecture!

Subscribe to Ram N Java for clean software architecture patterns, design pattern deep dives, and production-ready implementation guides!

🔔 Subscribe to Ram N Java

Understanding Multiple Receivers in Chain of Responsibility

The Chain of Responsibility is a powerful behavioral design pattern that decouples the sender of a request from its potential receivers by passing the request along a chain of handlers. While the classic variant often halts as soon as a single receiver handles the request, many modern architectural scenarios—such as logging pipelines, security filters, event dispatchers, and data enrichment workflows—require multiple receivers to inspect, process, and pass the request forward along the entire chain.

How Multiple Receiver Handling Works

  • Chained Handler Hierarchy: Each concrete handler maintains a reference to the next successor in the pipeline.
  • Non-Terminating Propagation: Instead of returning immediately after performing its operation, each handler executes its specific business logic and then explicitly delegates invocation to super.handleRequest() or nextHandler.handleRequest().
  • Incremental Request Enrichment: A single request object travels through each station in the sequence, allowing multiple handlers to validate, authenticate, transform, or log the payload sequentially.
  • Dynamic Pipeline Configuration: The sequence of handlers can be assembled or reordered dynamically at runtime without modifying client code or handler internals.

Key Components in the Implementation

  1. Handler Interface/Abstract Class: Declares the contract for handling requests and stores the reference to the next successor.
  2. Concrete Handlers: Individual handler classes that inspect the request, apply their domain-specific logic, and forward the request downstream.
  3. Client: Configures the sequence of handlers and initiates the pipeline by sending a request to the first link in the chain.

Architectural Advantages

  • Single Responsibility Principle (SRP): Isolates distinct processing concerns (such as validation, logging, and security) into separate, focused classes.
  • Open/Closed Principle (OCP): Allows adding, removing, or reordering processing steps without altering existing handler implementations.
  • Loose Coupling: The client remains completely agnostic of how many handlers process the request or their internal execution order.

Recommended Next Videos

Continue your deep dive into the Chain of Responsibility pattern with these related tutorials from our channel:


Click here to watch in Youtube : https://www.youtube.com/watch?v=tyGnCb-kE1I

Click the below Image to Enlarge
Chain of Responsibility Design pattern - Implementation
Chain of Responsibility Design pattern - Implementation - Class Diagram




































RsHandler.java

public abstract class RsHandler
{
RsHandler rsHandler;

public void nextHandler( RsHandler rsHandler )
{
this.rsHandler = rsHandler;
}

public abstract void dispatchRs( long requestedAmount );

}

HundredRsHandler.java

public class HundredRsHandler extends RsHandler
{

public void dispatchRs(long requestedAmount)
{
long numberofNotesToBeDispatched = requestedAmount / 100;
if (numberofNotesToBeDispatched > 0)
{
if(numberofNotesToBeDispatched>1)
{
System.out.println(numberofNotesToBeDispatched + " ,Hundred Rs notes are dispatched by HundredRsHandler\n");
}
else
{
System.out.println(numberofNotesToBeDispatched + " ,Hundred Rs note is dispatched by HundredRsHandler\n");

}
}

long pendingAmountToBeProcessed = requestedAmount % 100;

if (pendingAmountToBeProcessed > 0)
{
rsHandler.dispatchRs(pendingAmountToBeProcessed);

}

}

}

FiftyRsHandler.java

public class FiftyRsHandler extends RsHandler
{
public void dispatchRs(long requestedAmount)
{
long numberofNotesToBeDispatched = requestedAmount / 50;
if (numberofNotesToBeDispatched > 0)
{
if (numberofNotesToBeDispatched > 1)
{
System.out.println(numberofNotesToBeDispatched + " ,Fifty Rs notes are dispatched by FiftyRsHandler\n");
}
else
{
System.out.println(numberofNotesToBeDispatched + " ,Fifty Rs note is dispatched by FiftyRsHandler\n");

}

}

long pendingAmountToBeProcessed = requestedAmount % 50;

if (pendingAmountToBeProcessed > 0)
{
rsHandler.dispatchRs(pendingAmountToBeProcessed);

}

}
}


TwentyRsHandler.java

public class TwentyRsHandler extends RsHandler
{
public void dispatchRs(long requestedAmount)
{
long numberofNotesToBeDispatched = requestedAmount / 20;

if (numberofNotesToBeDispatched > 0)
{

if (numberofNotesToBeDispatched > 1)
{
System.out.println(numberofNotesToBeDispatched + " ,Twenty Rs notes are dispatched by TwentyRsHandler\n");
}
else
{
System.out.println(numberofNotesToBeDispatched + " ,Twenty Rs note is dispatched by TwentyRsHandler\n");

}
}

long pendingAmountToBeProcessed = requestedAmount % 20;

if (pendingAmountToBeProcessed > 0)
{
rsHandler.dispatchRs(pendingAmountToBeProcessed);

}

}
}


FiveRsHandler.java

public class FiveRsHandler extends RsHandler
{
public void dispatchRs(long requestedAmount)
{
long numberofNotesToBeDispatched = requestedAmount / 5;
if (numberofNotesToBeDispatched > 0)
{

if (numberofNotesToBeDispatched > 1)
{
System.out.println(numberofNotesToBeDispatched + " ,Five Rs notes are dispatched by FiveRsHandler\n");
}
else
{
System.out.println(numberofNotesToBeDispatched + " ,Five Rs note is dispatched by FiveRsHandler\n");

}
}

long pendingAmountToBeProcessed = requestedAmount % 5;

if (pendingAmountToBeProcessed > 0)
{
rsHandler.dispatchRs(pendingAmountToBeProcessed);

}

}
}


ATM.java

public class ATM
{
private static HundredRsHandler hundredRsHandler = new HundredRsHandler();
private static FiftyRsHandler   fiftyRsHandler   = new FiftyRsHandler();
private static TwentyRsHandler  twentyRsHandler  = new TwentyRsHandler();
private static FiveRsHandler    fiveRsHandler    = new FiveRsHandler();

static
{
// Prepare the chain of Handlers
hundredRsHandler.nextHandler(fiftyRsHandler);
fiftyRsHandler.nextHandler(twentyRsHandler);
twentyRsHandler.nextHandler(fiveRsHandler);
}

public void withdraw( long requestedAmount )
{

hundredRsHandler.dispatchRs(requestedAmount);
}
}


ChainOfResDemo.java

public class ChainOfResDemo
{

public static void main( String[] args )
{
ATM atm = new ATM();
System.out.println("\n ----------------Requested Amount 475-----------------------\n");
atm.withdraw(475);
System.out.println("\n ----------------Requested Amount 455-----------------------\n");
atm.withdraw(455);
System.out.println("\n ----------------Requested Amount 520-----------------------\n");
atm.withdraw(520);
}

}


Output

 ----------------Requested Amount 475-----------------------

4 ,Hundred Rs notes are dispatched by HundredRsHandler

1 ,Fifty Rs note is dispatched by FiftyRsHandler

1 ,Twenty Rs note is dispatched by TwentyRsHandler

1 ,Five Rs note is dispatched by FiveRsHandler


 ----------------Requested Amount 455-----------------------

4 ,Hundred Rs notes are dispatched by HundredRsHandler

1 ,Fifty Rs note is dispatched by FiftyRsHandler

1 ,Five Rs note is dispatched by FiveRsHandler


 ----------------Requested Amount 520-----------------------

5 ,Hundred Rs notes are dispatched by HundredRsHandler

1 ,Twenty Rs note is dispatched by TwentyRsHandler



No comments:

Post a Comment

Tutorials