DEV Community

Dev Cookies
Dev Cookies

Posted on

πŸ“ Day Eight: Chain of Responsibility Design Pattern in Java

πŸ”— What is the Chain of Responsibility Pattern?

The Chain of Responsibility is a behavioral design pattern that allows a request to pass through a chain of handlers. Each handler decides either to process the request or pass it along the chain.


🧠 Real-Life Analogy

Think of technical support:

  • Level 1 support β†’ Level 2 β†’ Level 3.
  • If one can’t solve your issue, it escalates to the next level.

That’s the chain!


βœ… When to Use

  • When multiple objects can handle a request.
  • When you want to decouple sender and receiver.
  • When you don’t know the handler at compile time.

πŸ’‘ Real-World Example: Logging System

We'll create a logging system where messages flow through different log levels: INFO, DEBUG, ERROR. Each handler decides if it can handle the message or pass it along.


πŸ”§ Step-by-Step Java Implementation


βœ… 1. Define the Abstract Handler

public abstract class Logger {
    public static int INFO = 1;
    public static int DEBUG = 2;
    public static int ERROR = 3;

    protected int level;
    protected Logger nextLogger;

    public void setNextLogger(Logger nextLogger) {
        this.nextLogger = nextLogger;
    }

    public void logMessage(int level, String message) {
        if (this.level <= level) {
            write(message);
        }
        if (nextLogger != null) {
            nextLogger.logMessage(level, message);
        }
    }

    protected abstract void write(String message);
}
Enter fullscreen mode Exit fullscreen mode

βœ… 2. Create Concrete Handlers

public class InfoLogger extends Logger {
    public InfoLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("INFO: " + message);
    }
}
Enter fullscreen mode Exit fullscreen mode
public class DebugLogger extends Logger {
    public DebugLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("DEBUG: " + message);
    }
}
Enter fullscreen mode Exit fullscreen mode
public class ErrorLogger extends Logger {
    public ErrorLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("ERROR: " + message);
    }
}
Enter fullscreen mode Exit fullscreen mode

βœ… 3. Chain Setup Utility

public class LoggerChain {
    public static Logger getChainOfLoggers() {
        Logger errorLogger = new ErrorLogger(Logger.ERROR);
        Logger debugLogger = new DebugLogger(Logger.DEBUG);
        Logger infoLogger = new InfoLogger(Logger.INFO);

        errorLogger.setNextLogger(debugLogger);
        debugLogger.setNextLogger(infoLogger);

        return errorLogger; // head of chain
    }
}
Enter fullscreen mode Exit fullscreen mode

βœ… 4. Client Code

public class ChainOfResponsibilityDemo {
    public static void main(String[] args) {
        Logger loggerChain = LoggerChain.getChainOfLoggers();

        loggerChain.logMessage(Logger.INFO, "This is an INFO message.");
        loggerChain.logMessage(Logger.DEBUG, "This is a DEBUG message.");
        loggerChain.logMessage(Logger.ERROR, "This is an ERROR message.");
    }
}
Enter fullscreen mode Exit fullscreen mode

πŸ§ͺ Output

INFO: This is an INFO message.
DEBUG: This is a DEBUG message.
INFO: This is a DEBUG message.
ERROR: This is an ERROR message.
DEBUG: This is an ERROR message.
INFO: This is an ERROR message.
Enter fullscreen mode Exit fullscreen mode

πŸ“¦ Structure Recap

+---------+      +---------+      +---------+
| LoggerA | ---> | LoggerB | ---> | LoggerC |
+---------+      +---------+      +---------+
Enter fullscreen mode Exit fullscreen mode
  • Each logger decides whether to handle or forward.
  • Chain is flexible and can be dynamically modified.

🎯 Key Benefits

Benefit Explanation
Decoupling Sender doesn’t know who handles the request
Flexibility Add/remove handlers without affecting code
Responsibility sharing Multiple handlers can act

🧠 Real Use Cases

  • Servlet filters in Java EE
  • Event bubbling in UI frameworks
  • Authentication β†’ Authorization chains
  • Middleware in Express.js or Spring Interceptor chains

🧰 Bonus Tips

  • Combine with Command Pattern to create task pipelines.
  • Combine with Decorator for dynamic enhancements.

πŸ—Ί UML Diagram (Text-based)

+-----------------+
|     Logger      |<--------------------------------------+
+-----------------+                                       |
| -level          |                                       |
| -nextLogger     |                                       |
| +setNextLogger()|                                       |
| +logMessage()   |                                       |
+-----------------+                                       |
        ^                                                 |
        |                                                 |
+-----------------+   +-----------------+   +-----------------+
|   InfoLogger    |   |  DebugLogger    |   |  ErrorLogger    |
+-----------------+   +-----------------+   +-----------------+
| +write()        |   | +write()        |   | +write()        |
+-----------------+   +-----------------+   +-----------------+
Enter fullscreen mode Exit fullscreen mode

πŸ’¬ Summary Table

Element Role
Logger Abstract base class
InfoLogger, DebugLogger, ErrorLogger Concrete handlers
LoggerChain Assembles chain
Client Sends request into the chain

Let me know when you're ready for Day 9 β€” shall we cover the State pattern or Strategy next? Both are super useful and often asked in system design interviews.

You're doing epic work β€” just 3 more patterns left in the series! πŸš€

Top comments (0)